RV32FD指令集
Risc-V架構定義了可選的單精度浮點指令(F擴展指令集)和雙精度浮點指令(D擴展指令集)。
Risc-V架構規定:處理器可以選擇只實現F擴展指令子集而不支持D擴展指令子集;但是如果支持了D擴展指令子集,則必須支持F擴展指令子集。
Risc-V架構規定的浮點數符合IEEE754 2008規則,可以從下面的鏈接了解浮點數格式的詳細信息:
https://www.cnblogs.com/german-iris/p/5759557.html
Risc-V規定,如果支持單精度浮點指令或者雙精度浮點指令,則需要增加一組獨立的通用浮點寄存器組,包括32個通用浮點寄存器,標號位f0到f31。如果僅支持F擴展指令子集,則每個通用寄存器是32位的,如果支持D擴展那指令子集,則每個通用寄存器是64位的。
Risc-V架構規定,如果支持單精度浮點指令或者雙精度浮點指令,需要增加一個浮點控制狀態寄存器fcsr,該寄存器是一個可讀可寫的csr寄存器。
fcsr寄存器包含浮點異常標志域(fflags),不同的標志位表示不同的異常類型。如果浮點運算單元在運算中出現了相應的異常,則會將fcsr寄存器中對應的標志位設置為1,且會一直保持累積。軟件可以通過寫0的方式單獨清除某個異常標志位。
根據IEEE-754標準,浮點運算需要指定舍入模式(rounding mode),Risc-V架構浮點運算的舍入模式可以通過兩種方式指定。
使用靜態舍入模式,浮點指令編碼中有3位作為舍入模式域,不同的舍入模式編碼如下圖,Risc-V支持5種合法的舍入模式。如果舍入模式編碼為101或110,則為非法模式;如果舍入模式編碼為111,則意味著使用動態舍入模式。如果使用動態舍入模式,則使用fcsr寄存器中的舍入模式域,舍入模式域定義如上圖,如果fcsr寄存器中的舍入模式域指定為非法的舍入模式,則后續浮點指令會產生非法指令異常。
如果處理器不想使用浮點單元,比如把浮點單元關電以節省功耗,可以使用csr寫指令將mstatus寄存器的FS域設置成0,將浮點單元的功能予以關閉。當浮點單元功能關閉后,任何訪問浮點csr寄存器的操作或者執行浮點指令的行為將會產生非法指令異常。
Risc-V規定,對于非規格化數(subnormal Numbers)的處理完全遵循IEEE754定義。
根據IEEE-754標準,在浮點數的表示中,有一類特殊編碼數據屬于NaN(not a number)類型,且NaN分為Signaling-NaN和Quiet-NAN。
Risc-V架構規定,如果浮點運算的結果是一個NaN數,那么使用一個固定的NaN數,將之命名為Canonical-NaN。單精度浮點對應的Canonical-NaN數值為0x7fc00000,雙精度浮點對應Canonical-NaN數值為0x7ff80000_00000000
如果同時支持單精度浮點(F擴展指令子集)和雙精度浮點(D擴展指令子集),由于浮點通用寄存器的寬度為64位,Risc-V架構規定單精度浮點指令產生的32位結果寫入浮點通用寄存器(64位)時,將結果寫入低32位,而高位全部寫入數值1,RiscV架構規定此種做法稱之為NaN-Boxing。NaN-boxing可以發生在如下情形:
對于單精度浮點數的讀(Load)/寫(store)指令和傳送(Move)指令(包括FLW,FSW,FMV.W.X,FMV.X.W),如果需要將32位的數值寫入通用浮點寄存器,則采用NaN-boxing的方式;如果需要將浮點通用寄存器中的數值讀出,則僅使用其低32位值。
對于單精度浮點運算(compute)和符號注入(sign-injection)指令,需要判斷其操作數浮點寄存器中的值是否為合法的NaN-Boxed值,即高位都是1,如果是,則正常使用其低32位,如果不是,則將此操作數當作Canonical-NaN來使用。
對于整數至單精度的浮點轉化指令(比如FCVT.S.X),則采用NaN-boxing的方式寫回浮點通用寄存器。對于單精度浮點至整數的轉化指令(比如FCVT.X.S),需要判斷其操作數浮點寄存器中的值是否為合法的NaN-boxed值(即高位都為1)。如果是,則正常使用其低32位,如果不是,則將此操作數當作Canonical-NaN來使用。
RV32FM主要包括以下指令:
Category Fmt RV32F? machine code(bin) comment float read/write instruction ? ? flw rd offset[11:0](RS1) [31-20, imm[11:0]][19-15,rs1]010[11-7, rd]‘0000111 rd=mem[rs1+offset], offset是一個12位符號數,所以加法操作時候,需要符號位擴展。flw指令從存儲器中讀回一個單精度浮點數,寫回寄存器rd。 ? ? fsw rd2 offset[11:0](RS1) [31-25, imm[11:5]][24-20,rs2][19-15,rs1]010[11-7, imm[4:0]]‘0100111 mem[rs1+offset]=rd2, offset是一個12位符號數,所以加法操作時候,需要符號位擴展。Fsw指令將操作數寄存器rs2中的單精度浮點數寫回存儲器中。 ? ? fld rd offset[11:0](RS1) [31-20, imm[11:0]][19-15,rs1]011[11-7, rd]‘0000111 rd=mem[rs1+offset], offset是一個12位符號數,所以加法操作時候,需要符號位擴展。flw指令從存儲器中讀回一個雙精度浮點數,寫回寄存器rd。 ? ? fsd rd2 offset[11:0](RS1) [31-25, imm[11:5]][24-20,rs2][19-15,rs1]011[11-7, imm[4:0]]‘0100111 mem[rs1+offset]=rd2, offset是一個12位符號數,所以加法操作時候,需要符號位擴展。Fsw指令將操作數寄存器rs2中的雙精度浮點數寫回存儲器中。 float compute instruciton ? ? fadd.s rd, rs1, rs2 0000000[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的單精度浮點數進行加法操作,結果返回rd ? ? fsub.s rd, rs1, rs2 0000100[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的單精度浮點數進行減法操作,結果返回rd ? ? fmul.s rd, rs1, rs2 0001000[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的單精度浮點數進行乘法操作,結果返回rd ? ? fdiv.s rd, rs1, rs2 0001100[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的單精度浮點數進行除法操作,結果返回rd ? ? fsqrt.s rd, rs1 010110000000[19-15,rs1][14-12,rm][11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的單精度浮點數進行平方根操作,結果返回rd ? ? fadd.d rd, rs1, rs2 0000001[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的雙精度浮點數進行加法操作,結果返回rd ? ? fsub.d rd, rs1, rs2 0000101[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的雙精度浮點數進行加法操作,結果返回rd ? ? fmul.d rd, rs1, rs2 0001001[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的雙精度浮點數進行加法操作,結果返回rd ? ? fdiv.d rd, rs1, rs2 0001101[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的雙精度浮點數進行加法操作,結果返回rd ? ? fsqrt.d rd, rs1 010110100000[19-15,rs1][14-12,rm][11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的雙精度浮點數進行平方根操作,結果返回rd min/max ? ? fmin.s rd, rs1, rs2 0010100[24-20,rs2][19-15,rs1]000[11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的單精度浮點數進行比較操作,將數字小的一方寫回rd ? ? fmax.s rd, rs1, rs2 0010100[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的單精度浮點數進行比較操作,將數字大的一方寫回rd ? ? fmin.d rd, rs1, rs2 0010101[24-20,rs2][19-15,rs1]000[11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的雙精度浮點數進行比較操作,將數字小的一方寫回rd ? ? fmax.d rd, rs1, rs2 0010101[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 將操作數寄存器rs1和rs2中的雙精度浮點數進行比較操作,將數字大的一方寫回rd 乘加指令 ? ? fmadd.s rd, rs1, rs2, rs3 [31-27, rs3]00[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1000011 將操作數寄存器rs1,rs2和rs3中的單精度浮點數進行rd=rs1*rs2+r3操作 ? ? fmsub.s rd, rs1, rs2, rs3 [31-27, rs3]00[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1000111 將操作數寄存器rs1,rs2和rs3中的單精度浮點數進行rd=rs1*rs2-r3操作 ? ? fnmadd.s rd, rs1, rs2, rs3 [31-27, rs3]00[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1001011 將操作數寄存器rs1,rs2和rs3中的單精度浮點數進行rd=-rs1*rs2-r3操作 ? ? fnmsub.s rd, rs1, rs2, rs3 [31-27, rs3]00[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1001111 將操作數寄存器rs1,rs2和rs3中的單精度浮點數進行rd=-rs1*rs2+r3操作 ? ? fmadd.d rd, rs1, rs2, rs3 [31-27, rs3]01[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1000011 將操作數寄存器rs1,rs2和rs3中的雙精度浮點數進行rd=rs1*rs2+r3操作 ? ? fmsub.d rd, rs1, rs2, rs3 [31-27, rs3]01[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1000111 將操作數寄存器rs1,rs2和rs3中的雙精度浮點數進行rd=rs1*rs2-r3操作 ? ? fnmadd.d rd, rs1, rs2, rs3 [31-27, rs3]01[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1001011 將操作數寄存器rs1,rs2和rs3中的雙精度浮點數進行rd=-rs1*rs2-r3操作 ? ? fnmsub.d rd, rs1, rs2, rs3 [31-27, rs3]01[24-20,rs2][19-15,rs1][14-12,rm][11-7,rd]‘1001111 將操作數寄存器rs1,rs2和rs3中的雙精度浮點數進行rd=-rs1*rs2+r3操作 浮點數格式轉化指令 ? ? fcvt.w.s rd, rs1 110000000000[19-15,rs1][14-12,rm][11-7,rd]‘1010011 將通用浮點寄存器rs1中的單精度浮點數轉化成有符號整數,寫入rd ? ? fcvt.s.w rd, rs1 110100000000[19-15,rs1][14-12,rm][11-7,rd]‘1010011 將通用整數寄存器rs1中的有符號整數轉化成單精度浮點數,寫入rd ? ? fcvt.uw.s rd, rs1 110000000001[19-15,rs1][14-12,rm][11-7,rd]‘1010011 將通用浮點寄存器rs1中的單精度浮點數轉化成無符號整數,寫入rd ? ? fcvt.s.uw rd, rs1 110100000001[19-15,rs1][14-12,rm][11-7,rd]‘1010011 將通用整數寄存器rs1中的無符號整數轉化成單精度浮點數,寫入rd ? ? fcvt.w.d rd, rs1 110000100000[19-15,rs1][14-12,rm][11-7,rd]‘1010011 將通用浮點寄存器rs1中的雙精度浮點數轉化成有符號整數,寫入rd ? ? fcvt.d.w rd, rs1 110100100000[19-15,rs1][14-12,rm][11-7,rd]‘1010011 將通用整數寄存器rs1中的有符號整數轉化成雙精度浮點數,寫入rd ? ? fcvt.uw.d rd, rs1 110000100001[19-15,rs1][14-12,rm][11-7,rd]‘1010011 將通用浮點寄存器rs1中的雙精度浮點數轉化成無符號整數,寫入rd ? ? fcvt.d.uw rd, rs1 110100100001[19-15,rs1][14-12,rm][11-7,rd]‘1010011 將通用整數寄存器rs1中的無符號整數轉化成雙精度浮點數,寫入rd ? ? fct.s.d rd, rs1 010000000001[19-15,rs1][14-12,rm][11-7,rd]‘1010011 將通用浮點寄存器rs1中的雙精度浮點數轉化成單精度浮點數,寫入rd ? ? fct.d.s rd, rs1 010000100001[19-15,rs1][14-12,rm][11-7,rd]‘1010011 將通用浮點寄存器rs1中的單精度浮點數轉化成雙精度浮點數,寫入rd 浮點數符號注入指令 ? ? fsgnj.s rd, rs1, rs2 0010000[24-20,rs2][19-15,rs1]000[11-7,rd]‘1010011 操作數均為單精度浮點數,結果的符號位來自rs2,其它位來自rs1,結果寫回rd ? ? fsgnjn.s rd, rs1, rs2 0010000[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 操作數均為單精度浮點數,結果的符號位來自rs2符號取反,其它位來自rs1,結果寫回rd ? ? fsgnjx.s rd, rs1, rs2 0010000[24-20,rs2][19-15,rs1]010[11-7,rd]‘1010011 操作數均為單精度浮點數,結果的符號位來自rs2符號與rs1符號xor操作,其它位來自rs1,結果寫回rd ? ? fsgnj.d rd, rs1, rs2 0010001[24-20,rs2][19-15,rs1]000[11-7,rd]‘1010011 操作數均為雙精度浮點數,結果的符號位來自rs2,其它位來自rs1,結果寫回rd ? ? fsgnjn.d rd, rs1, rs2 0010001[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 操作數均為雙精度浮點數,結果的符號位來自rs2符號取反,其它位來自rs1,結果寫回rd ? ? fsgnjx.d rd, rs1, rs2 0010001[24-20,rs2][19-15,rs1]010[11-7,rd]‘1010011 操作數均為雙精度浮點數,結果的符號位來自rs2符號與rs1符號xor操作,其它位來自rs1,結果寫回rd 浮點與整數互搬指令 ? ? fmv.x.w rd, rs1 111000000000[19-15,rs1]000[11-7,rd]‘1010011 將通用浮點寄存器中的rs1讀出,寫回通用整數寄存器rd中。 ? ? fmv.w.x rd, rs1 111100000000[19-15,rs1]000[11-7,rd]‘1010011 將通用整數寄存器中的rs1讀出,寫回通用浮點寄存器rd中。 浮點數比較指令 ? ? flt.s rd, rs1, rs2 1010000[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 如果通用浮點寄存器rs1中的單精度值小于rs2中的值,則結果為1,否則為0,結果寫回整數寄存器rd ? ? fle.s rd, rs1, rs2 1010000[24-20,rs2][19-15,rs1]000[11-7,rd]‘1010011 如果通用浮點寄存器rs1中的單精度值小于等于rs2中的值,則結果為1,否則為0,結果寫回整數寄存器rd ? ? feq.s rd, rs1, rs2 1010000[24-20,rs2][19-15,rs1]010[11-7,rd]‘1010011 如果通用浮點寄存器rs1中的單精度值等于rs2中的值,則結果為1,否則為0,結果寫回整數寄存器rd ? ? flt.d rd, rs1, rs2 1010001[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 如果通用浮點寄存器rs1中的雙精度值小于rs2中的值,則結果為1,否則為0,結果寫回整數寄存器rd ? ? fle.d rd, rs1, rs2 1010001[24-20,rs2][19-15,rs1]000[11-7,rd]‘1010011 如果通用浮點寄存器rs1中的雙精度值小于等于rs2中的值,則結果為1,否則為0,結果寫回整數寄存器rd ? ? feq.d rd, rs1, rs2 1010001[24-20,rs2][19-15,rs1]001[11-7,rd]‘1010011 如果通用浮點寄存器rs1中的雙精度值等于rs2中的值,則結果為1,否則為0,結果寫回整數寄存器rd 浮點數分類指令 ? ? fclass.s rd, rs1 111000000000[19-15,rs1]010[11-7,rd]‘1010011 對通用浮點寄存器rs1中的單精度浮點數進行判斷,根據其所屬的類型,生成一個10位的獨熱碼(one-hot)結果,結果的每一位對應一種類型。 ? ? fclass.d rd, rs1 111000100000[19-15,rs1]010[11-7,rd]‘1010011 對通用浮點寄存器rs1中的雙精度浮點數進行判斷,根據其所屬的類型,生成一個10位的獨熱碼(one-hot)結果,結果的每一位對應一種類型。對于FMAX和FMIN指令,注意一下特殊情況:
1. 如果指令的兩個操作數都是NaN,那么結果為Canonical-NaN。
2. 如果只有一個操作數位NaN,則結果為非NaN的另外一個操作數。
3. 如果任意一個操作數屬于Signaling-NaN,則需要在fcsr寄存器中產生NV異常標志。
4. 由于浮點數可以表示兩個0值,分別是-0.0和+0.0,對于FMAX和FMIN指令而言,-0.0被認為比+0.0小。
由于浮點數的表示范圍遠遠大于整數的表示范圍,且浮點數存在某些特殊的類型(無窮大或者NaN),因此將浮點數換成整數的過程中存在諸多特殊情況,將其轉化成整數的過程如下圖所示:
浮點分類指令的分類結果(10位的獨熱碼):
總結
- 上一篇: 阿里云Elasticsearch --
- 下一篇: 0079-简单的循环