RV32I是32位基礎整數指令集,它支持32位尋址空間,支持字節地址訪問,僅支持小端格式(little-endian,高地址高位,低地址地位),寄存器也是32位整數寄存器。RV32I指令集的目的是盡量簡化硬件的實施設計,所以它只有40條指令(備注,之前是47條指令,在最新的規范中,一些csr指令被放在擴展指令集中)。這40條指令幾乎能夠模擬其它任何擴展指令(除了A擴展指令,因為原子指令需要硬件支持)。如果用更簡單的實現方式,比如對於ECALL和EBREAK指令,調用時候,系統總是自陷(trap),以及用NOP指令模擬Fence指令,則RV32I甚至可以減少到38條指令(備注:在RISC V中,NOP指令是偽代碼,其實就是addi, x0,x0,0)。
實際上要實現機器模式的RiscV特權架構,還需要6條csr指令,之前這些指令都是在RV32I中的,現在被放在擴展指令集 Zicsr中了。所以說要實現一個完整的RiscV系統,至少要實現RV32I+Zicsr指令集。
在RV32I指令集架構中,包括32個通用目的寄存器,其中x0被預留為常數0,其它31個寄存器(x1-x31)是普通的通用整數寄存器。在Risc-V匯編語言中,每個通用寄存器都有一個對應的ABI名字,也就是說在匯編語言中,x1等價於ra,它們都會匯編成相同的機器碼。對於RV32I,通用寄存器是32位的寄存器,xlen=32;對於RV64I,通用寄存器是64位寄存器,xlen=64。
在Risc-V架構中,要得到當前指令pc(指令在存儲器中的位置,instruction program counter),可以通過AUIPC指令,把它讀入到一個通用寄存器中。
寄存器 | ABI名字 | 注釋 | Saver |
x0 | zero | Hard-wired zero,常數0 | |
x1 | ra | Return address | caller,調用函數的指令pc |
x2 | sp | Stack pointer | callee,被調用的函數指令pc |
x3 | gp | Global pointer | |
x4 | tp | Thread pointer | |
x5 | t0 | Temporary/alternate link register | caller |
x6 | t1 | Temporaries | caller |
x7 | t2 | Temporaries | caller |
x8 | s0/fp | Saved register/frame pointer | caller |
x9 | s1 | Saved register | caller |
x10 | a0 | Function arguments/return values | caller |
x11 | a1 | Function arguments/return values | caller |
x12 | a2 | Function arguments | caller |
x13 | a3 | Function arguments | caller |
x14 | a4 | Function arguments | caller |
x15 | a5 | Function arguments | caller |
x16 | a6 | Function arguments | caller |
x17 | a7 | Function arguments | caller |
x18 | s2 | Saved registers | caller |
x19 | s3 | Saved registers | caller |
x20 | s4 | Saved registers | caller |
x21 | s5 | Saved registers | caller |
x22 | s6 | Saved registers | caller |
x23 | s7 | Saved registers | caller |
x24 | s8 | Saved registers | caller |
x25 | s9 | Saved registers | caller |
x26 | s10 | Saved registers | caller |
x27 | s11 | Saved registers | caller |
x28 | t3 | Temporaries | caller |
x29 | t4 | Temporaries | caller |
x30 | t5 | Temporaries | caller |
x31 | t6 | Temporaries | caller |
Base指令格式:
RV32I指令格式包括以下6種,每種指令格式都是固定的32位指令,所以指令在內存中必須4字節對齊。比如一個分支跳轉指令,當條件判定是跳轉的時候,而目的地址不是4字節對齊,則產生指令地址不對齊異常。無條件跳轉指令也是如此,目的地址不是4字節對齊,則產生指令地址不對齊異常。備注:但在實際應用中,很難會產生這種錯誤,因為在匯編語言中,我們用label作為跳轉目的,匯編器會自動幫我們產生字節對齊的偏移地址。
其中rd表示目的寄存器,rs1是源操作數寄存器1,rs2是源操作數寄存器2。
imm表示指令中的立即數,比如imm[11:0],表示一個12位的立即數,它的高20位會符號位擴展,也就是用最左邊的位imm[11]來進行擴展。imm[31:12]表示一個32位的立即數,它的低12位會補0。備注: csr指令中的5位立即數不需要符號位擴展。
下圖是各種指令格式擴展后的32位立即數。
分支指令(B 類型)的立即數字段在 S 類型的基礎上旋轉了 1 位。跳轉指令(J類型)的直接字段在 U 類型的基礎上旋轉了 12 位。因此,RISC-V 實際上只有四種基本格式,但我們可以保守地認為它有六種格式。
RV32I整數指令集
RV32I整數指令集分為幾個種類:
1.Load和store指令
RV32I是一個load /store架構,所有的memory訪問都是通過load/store指令,其它指令都是在寄存器之間或者寄存器和立即數之間進行運算,比如加法指令,減法指令等等。注意,裝入目的寄存器如果為x0,將會產生一個異常。Load/Store指令在memory和寄存器之間傳輸數據,Load指令編碼為I型,store指令編碼為S型。計算memory地址時候,imm都會符號擴展成32位,然后和rs1相加,得到memory地址。為了提高性能,load/store指令應該盡量對齊地址,比如lw指令,訪問地址應該4字節對齊,lh訪問地址應該雙字節對齊。根據微架構實現的不同,不對齊地址的訪問可能會比較慢,而且地址對齊訪問,能夠確保是原子操作,不對齊的話為了讀取和存儲數據正確,還要進行額外的同步操作。
lb
lb rd, offset(rs1) //x[rd] = sext(M[x[rs1] + sext(offset)][7:0])
字節加載 (Load Byte). I-type, RV32I and RV64I.
從地址 x[rs1] + sign-extend(offset)讀取一個字節,經符號位擴展后寫入x[rd]。
imm(offset) | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
lb | I | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
例子:
Disassembly of section .text:
00000000 <.text>:
0: 00510503 lb x10,5(x2)
4: fec18283 lb x5,-20(x3)
注:立即數為補碼表示
lh
lh rd, offset(rs1) //x[rd] = sext(M[x[rs1] + sext(offset)][15:0])
半字加載 (Load Halfword). I-type, RV32I and RV64I.
從地址 x[rs1] + sign-extend(offset)讀取兩個字節,經符號位擴展后寫入 x[rd]。
imm(offset) | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
lh | I | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
例子:
0: 00511503 lh x10,5(x2)
lw
lw rd, offset(rs1) //x[rd] = sext(M[x[rs1] + sext(offset)][31:0])
字加載 (Load Word). I-type, RV32I and RV64I.
從地址 x[rs1] + sign-extend(offset)讀取四個字節,寫入 x[rd]。對於 RV64I,結果要進行符號位擴展。
壓縮形式: c.lwsp rd, offset; c.lw rd, offset(rs1)
imm(offset) | ||||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | |||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | RV32I |
lw | I | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | √ |
例子:
0: 00512503 lw x10,5(x2)
lbu
lbu rd, offset(rs1) //x[rd] = M[x[rs1] + sext(offset)][7:0]
無符號字節加載 (Load Byte, Unsigned). I-type, RV32I and RV64I.
從地址 x[rs1] + sign-extend(offset)讀取一個字節,經零擴展后寫入 x[rd]。
imm(offset) | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
lbu | I | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
例子:
0: 00514503 lbu x10,5(x2)
lhu
lhu rd, offset(rs1) //x[rd] = M[x[rs1] + sext(offset)][15:0]無符號半字加載 (Load Halfword, Unsigned). I-type, RV32I and RV64I.
從地址 x[rs1] + sign-extend(offset)讀取兩個字節,經零擴展后寫入 x[rd]。
imm(offset) | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
lhu | I | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
例子:
0: 00515503 lhu x10,5(x2)
sb
sb rs2, offset(rs1) //M[x[rs1] + sext(offset)] = x[rs2][7: 0]存字節(Store Byte). S-type, RV32I and RV64I.
將 x[rs2]的低位字節存入內存地址 x[rs1]+sign-extend(offset)。
imm(offset) | imm(offset) | ||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | rs2 | rs1 | func3 | 4 | 3 | 2 | 1 | 0 | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
sb | S | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
例子:
0: 00520123 sb x5,2(x4) # 0x2
sh
sh rs2, offset(rs1) //M[x[rs1] + sext(offset) = x[rs2][15: 0]
存半字(Store Halfword). S-type, RV32I and RV64I.
將 x[rs2]的低位 2 個字節存入內存地址 x[rs1]+sign-extend(offset)。
imm(offset) | imm(offset) | ||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | rs2 | rs1 | func3 | 4 | 3 | 2 | 1 | 0 | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
sh | S | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
例子:
4: 00521123 sh x5,2(x4) # 0x2
sw
sw rs2, offset(rs1) //M[x[rs1] + sext(offset) = x[rs2][31: 0]
存字(Store Word). S-type, RV32I and RV64I.
將 x[rs2]的低位 4 個字節存入內存地址 x[rs1]+sign-extend(offset)。
壓縮形式: c.swsp rs2, offset; c.sw rs2, offset(rs1)
imm(offset) | imm(offset) | ||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | rs2 | rs1 | func3 | 4 | 3 | 2 | 1 | 0 | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
sw | S | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
例子:
8: 00522123 sw x5,2(x4) # 0x2
2.整數計算指令(算術,邏輯指令,比較指令以及移位指令)
計算指令在寄存器和寄存器之間,或者在寄存器和立即數之間進行算術或邏輯運算。指令格式為I,R,U。
整數計算指令不會產生異常,但我們可以通過分支指令增加溢出(overflow)檢測,比如對於無符號數加法:
add t0, t1, t2; bltu t0, t1, overflow; //如果t0<t1,則跳轉到溢出處理
對於有符號數,如果知道符號位,則可以用下面代碼:
addi t0, t1, +imm; blt t0, t1, overflow; //t0<t1,則跳轉到溢出處理,因為imm為正數
對於通用有符號數加法,可以用下面的指令:
add t0, t1, t2; slti t3, t2, 0; //如果t2<0, t3=1 slt t4, t0, t1; //如果t0<t1, t4=1 bne t3, t4, overflow; //如果t3!=t4, 跳轉到溢出程序處理
算術指令:
add
add rd, rs1, rs2 //x[rd] = x[rs1] + x[rs2]
把寄存器 x[rs2]加到寄存器 x[rs1]上,結果寫入 x[rd]。忽略算術溢出。
加 (Add). R-type, RV32I and RV64I
壓縮形式: c.add rd, rs2; c.mv rd, rs2
func7 | rs2 | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
add | R | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
例子:
0: 00a48433 add x8,x9,x10
addi
addi rd, rs1, immediate //x[rd] = x[rs1] + sext(immediate)
加立即數(Add Immediate). I-type, RV32I and RV64I.
把符號位擴展的立即數加到寄存器 x[rs1]上,結果寫入 x[rd]。忽略算術溢出。
壓縮形式: c.li rd, imm; c.addi rd, imm; c.addi16sp imm; c.addi4spn rd, imm
imm | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
addi | I | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
我們可以用addi指令實現move指令, addi rd, rs1, 0 <=>mv rd,rs1 //x[rd]=x[rs1]
例子:
0: 01430513 addi x10,x6,20
sub
sub rd, rs1, rs2 //x[rd] = x[rs1] - x[rs2]
減(Substract). R-type, RV32I and RV64I.
x[rs1]減去 x[rs2],結果寫入 x[rd]。忽略算術溢出。
壓縮形式: c.sub rd, rs2
func7 | rs2 | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
sub | R | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
例子:
0: 40a48433 sub x8,x9,x10
lui
lui rd, immediate //x[rd] = sext(immediate[31:12] << 12)
高位立即數加載 (Load Upper Immediate). U-type, RV32I and RV64I.
20 位立即數 immediate 左移 12 位, 並將低 12 位置零, 寫入 x[rd]中。
壓縮形式: c.lui rd, imm
imm | |||||||||||||||||||||||||||||||||
19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rd | opcode | ||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
lui | U | 0 | 1 | 1 | 0 | 1 | 1 | 1 |
例子:
0: 00003237 lui x4,0x3
4: 000141b7 lui x3,0x14
8: 000102b7 lui x5,0x10
lui x5,-0x10 注意:立即數不能為負,范圍是0..1048575。
mm.s: Assembler messages:
mm.s:1: Error: lui expression not in range 0..1048575,
auipc
auipc rd, immediate //x[rd] = pc + sext(immediate[31:12] << 12)
PC 加立即數 (Add Upper Immediate to PC). U-type, RV32I and RV64I.
把符號位擴展的 20 位(左移 12 位)立即數加到 pc 上,結果寫入 x[rd]。
imm | |||||||||||||||||||||||||||||||||
19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rd | opcode | ||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
auipc | U | 0 | 0 | 1 | 0 | 1 | 1 | 1 |
例子:
0: 0000a297 auipc x5,0xa
用 auipc x5,0 我們能得到當前的pc值。
邏輯指令:
xor
xor rd, rs1, rs2 //x[rd] = x[rs1] ^ x[rs2]
異或(Exclusive-OR). R-type, RV32I and RV64I.
x[rs1]和 x[rs2]按位異或,結果寫入 x[rd]。
壓縮形式: c.xor rd, rs2
func7 | rs2 | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
xor | R | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
例子:
c: 00a4c433 xor x8,x9,x10
xori
xori rd, rs1, immediate //x[rd] = x[rs1] ^ sext(immediate)
立即數異或(Exclusive-OR Immediate). I-type, RV32I and RV64I.
x[rs1]和有符號擴展的 immediate 按位異或,結果寫入 x[rd]。
壓縮形式: c.xor rd, rs2
imm | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||
xori | I | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
例子:
0: 00224293 xori x5,x4,2
or
or rd, rs1, rs2 //x[rd] = x[rs1] | x[rs2]
取或(OR). R-type, RV32I and RV64I.
把寄存器 x[rs1]和寄存器 x[rs2]按位取或,結果寫入 x[rd]。
壓縮形式: c.or rd, rs2
func7 | rs2 | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
or | R | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
例子:
18: 00a4e433 or x8,x9,x10
ori
ori rd, rs1, immediate //x[rd] = x[rs1] | sext(immediate)
立即數取或(OR Immediate). R-type, RV32I and RV64I.
把寄存器 x[rs1]和有符號擴展的立即數 immediate 按位取或,結果寫入 x[rd]。
壓縮形式: c.or rd, rs2
imm | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
ori | I | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
例子:
0: 00226293 ori x5,x4,2
and
and rd, rs1, rs2 //x[rd] = x[rs1] & x[rs2]
與 (And). R-type, RV32I and RV64I.
將寄存器 x[rs1]和寄存器 x[rs2]位與的結果寫入 x[rd]。
壓縮形式: c.and rd, rs2
func7 | rs2 | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||||||
and | R | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
例子:
1c: 00a4f433 and x8,x9,x10
andi
andi rd, rs1, immediate //x[rd] = x[rs1] & sext(immediate)
與立即數 (And Immediate). I-type, RV32I and RV64I.
把符號位擴展的立即數和寄存器 x[rs1]上的值進行位與,結果寫入 x[rd]。
壓縮形式: c.andi rd, imm
imm | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
andi | I | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
例子:
0: 00227293 andi x5,x4,2
移位指令:
sll
sll rd, rs1, rs2 //x[rd] = x[rs1] ≪ x[rs2]
邏輯左移(Shift Left Logical). R-type, RV32I and RV64I.
把寄存器 x[rs1]左移 x[rs2]位,空出的位置填入 0,結果寫入 x[rd]。 x[rs2]的低 5 位(如果是RV64I 則是低 6 位)代表移動位數,其高位則被忽略。
func7 | rs2 | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
sll | R | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
例子:
0: 00a49433 sll x8,x9,x10
slli
slli rd, rs1, shamt //x[rd] = x[rs1] ≪ shamt
立即數邏輯左移(Shift Left Logical Immediate). I-type, RV32I and RV64I.
把寄存器 x[rs1]左移 shamt位,空出的位置填入 0,結果寫入 x[rd]。對於 RV32I,僅當 shamt[5]=0
時,指令才是有效的。
壓縮形式: c.slli rd, shamt
shamt | |||||||||||||||||||||||||||||||||
5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
slli | I | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
例子:
0: 00511513 slli x10,x2,0x5
srl
srl rd, rs1, rs2 //x[rd] = (x[rs1] ≫u x[rs2])
邏輯右移(Shift Right Logical). R-type, RV32I and RV64I.
把寄存器 x[rs1]右移 x[rs2]位,空出的位置填入 0,結果寫入 x[rd]。 x[rs2]的低 5 位(如果是 RV64I 則是低 6 位)代表移動位數,其高位則被忽略。
func7 | rs2 | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
srl | R | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
例子:
10: 00a4d433 srl x8,x9,x10
srli
srli rd, rs1, shamt //x[rd] = (x[rs1] ≫u shamt)
立即數邏輯右移(Shift Right Logical Immediate). I-type, RV32I and RV64I.
把寄存器 x[rs1]右移 shamt位,空出的位置填入 0,結果寫入 x[rd]。對於 RV32I,僅當 shamt[5]=0 時,指令才是有效的。
壓縮形式: c.srli rd, shamt
shamt | |||||||||||||||||||||||||||||||||
5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
srli | I | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
例子:
0: 00515513 srli x10,x2,0x5
sra
sra rd, rs1, rs2 //x[rd] = (x[rs1] ≫s x[rs2])
算術右移(Shift Right Arithmetic). R-type, RV32I and RV64I.
把寄存器 x[rs1]右移 x[rs2]位,空位用 x[rs1]的最高位填充,結果寫入 x[rd]。 x[rs2]的低 5 位 (如果是 RV64I 則是低 6 位)為移動位數,高位則被忽略。
func7 | rs2 | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
sra | R | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
例子:
14: 40a4d433 sra x8,x9,x10
srai
srai rd, rs1, shamt //x[rd] = (x[rs1] ≫s shamt)
立即數算術右移(Shift Right Arithmetic Immediate). I-type, RV32I and RV64I.
把寄存器 x[rs1]右移 shamt 位,空位用 x[rs1]的最高位填充,結果寫入 x[rd]。對於 RV32I, 僅當 shamt[5]=0 時指令有效。
壓縮形式: c.srai rd, shamt
shamt | |||||||||||||||||||||||||||||||||
5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
srai | I | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
例子:
0: 40515513 srai x10,x2,0x5
比較指令:
slt
slt rd, rs1, rs2 //x[rd] = (x[rs1] <s x[rs2])
小於則置位(Set if Less Than). R-type, RV32I and RV64I.
比較 x[rs1]和 x[rs2]中的數,如果 x[rs1]更小,向 x[rd]寫入 1,否則寫入 0。
func7 | rs2 | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
slt | R | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
例子:
4: 00a4a433 slt x8,x9,x10
slti
slti rd, rs1, immediate //x[rd] = (x[rs1] <s sext(immediate))
小於立即數則置位(Set if Less Than Immediate). I-type, RV32I and RV64I.
比較 x[rs1]和有符號擴展的 immediate,如果 x[rs1]更小,向 x[rd]寫入 1,否則寫入 0。
imm | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
slti | I | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
例子:
0: 00222293 slti x5,x4,2
sltu
sltu rd, rs1, rs2 //x[rd] = (x[rs1] <u x[rs2])
無符號小於則置位(Set if Less Than, Unsigned). R-type, RV32I and RV64I.
比較 x[rs1]和 x[rs2],比較時視為無符號數。如果 x[rs1]更小,向 x[rd]寫入 1,否則寫入 0。
func7 | rs2 | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
sltu | R | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
例子:
8: 00a4b433 sltu x8,x9,x10
sltiu
sltiu rd, rs1, immediate //x[rd] = (x[rs1] <u sext(immediate))
無符號小於立即數則置位(Set if Less Than Immediate, Unsigned). I-type, RV32I and RV64I.
比較 x[rs1]和有符號擴展的 immediate,比較時視為無符號數。如果 x[rs1]更小,向 x[rd]寫入 1,否則寫入 0
imm | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
sltiu | I | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
例子:
0: 00223293 sltiu x5,x4,2
3. 控制指令,包括無條件跳轉指令和條件跳轉指令
beq
beq rs1, rs2, offset //if (rs1 == rs2) pc += sext(offset)
相等時分支跳轉 (Branch if Equal). B-type, RV32I and RV64I.
若寄存器 x[rs1]和寄存器 x[rs2]的值相等,把 pc 的值設為當前值加上符號位擴展的偏移 offset。
壓縮形式: c.beqz rs1, offset
imm | imm | ||||||||||||||||||||||||||||||||
12 | 10 | 9 | 8 | 7 | 6 | 5 | rs2 | rs1 | func3 | 4 | 3 | 2 | 1 | 11 | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
beq | B | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
例子:
00000000 <label-0x8>:
0: 00628463 beq x5,x6,8 <label>
4: 00a48433 add x8,x9,x10
00000008 <label>:
8: 00d605b3 add x11,x12,x13
bne
bne rs1, rs2, offset //if (rs1 ≠ rs2) pc += sext(offset)
不相等時分支跳轉 (Branch if Not Equal). B-type, RV32I and RV64I.
若寄存器 x[rs1]和寄存器 x[rs2]的值不相等,把 pc 的值設為當前值加上符號位擴展的偏移offset。
壓縮形式: c.bnez rs1, offset
imm | imm | ||||||||||||||||||||||||||||||||
12 | 10 | 9 | 8 | 7 | 6 | 5 | rs2 | rs1 | func3 | 4 | 3 | 2 | 1 | 11 | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
bne | B | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
例子:
00000000 <label-0x8>:
0: 00629463 bne x5,x6,8 <label>
4: 00a48433 add x8,x9,x10
00000008 <label>:
8: 00d605b3 add x11,x12,x13
blt
blt rs1, rs2, offset //if (rs1 <s rs2) pc += sext(offset)
小於時分支跳轉 (Branch if Less Than). B-type, RV32I and RV64I.
若寄存器 x[rs1]的值小於寄存器 x[rs2]的值(均視為二進制補碼),把 pc 的值設為當前值加上符號位擴展的偏移 offset。
imm | imm | ||||||||||||||||||||||||||||||||
12 | 10 | 9 | 8 | 7 | 6 | 5 | rs2 | rs1 | func3 | 4 | 3 | 2 | 1 | 11 | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
blt | B | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
例子:
00000000 <label-0x8>:
0: 0062c463 blt x5,x6,8 <label>
4: 00a48433 add x8,x9,x10
00000008 <label>:
8: 00d605b3 add x11,x12,x13
bge
bge rs1, rs2, offset //if (rs1 ≥s rs2) pc += sext(offset)
大於等於時分支 跳轉(Branch if Greater Than or Equal). B-type, RV32I and RV64I.
若寄存器 x[rs1]的值大於等於寄存器 x[rs2]的值(均視為二進制補碼),把 pc 的值設為當前值加上符號位擴展的偏移 offset。
imm | imm | ||||||||||||||||||||||||||||||||
12 | 10 | 9 | 8 | 7 | 6 | 5 | rs2 | rs1 | func3 | 4 | 3 | 2 | 1 | 11 | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
bge | B | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
例子:
00000000 <label-0x8>:
0: 0062d463 bge x5,x6,8 <label>
4: 00a48433 add x8,x9,x10
00000008 <label>:
8: 00d605b3 add x11,x12,x13
bltu
bltu rs1, rs2, offset //if (rs1 <u rs2) pc += sext(offset)
無符號小於時分支跳轉 (Branch if Less Than, Unsigned). B-type, RV32I and RV64I.
若寄存器 x[rs1]的值小於寄存器 x[rs2]的值(均視為無符號數),把 pc 的值設為當前值加上
符號位擴展的偏移 offset。
imm | imm | ||||||||||||||||||||||||||||||||
12 | 10 | 9 | 8 | 7 | 6 | 5 | rs2 | rs1 | func3 | 4 | 3 | 2 | 1 | 11 | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
bltu | B | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
例子:
00000000 <label-0x8>:
0: 0062e463 bltu x5,x6,8 <label>
4: 00a48433 add x8,x9,x10
00000008 <label>:
8: 00d605b3 add x11,x12,x13
bgeu
bgeu rs1, rs2, offset //if (rs1 ≥u rs2) pc += sext(offset)
無符號大於等於時分支跳轉 (Branch if Greater Than or Equal, Unsigned). B-type, RV32I and RV64I.
若寄存器 x[rs1]的值大於等於寄存器 x[rs2]的值(均視為無符號數),把 pc 的值設為當前值加上符號位擴展的偏移 offset。
imm | imm | ||||||||||||||||||||||||||||||||
12 | 10 | 9 | 8 | 7 | 6 | 5 | rs2 | rs1 | func3 | 4 | 3 | 2 | 1 | 11 | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
bgeu | B | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
例子:
00000000 <label-0x8>:
0: 0062f463 bgeu x5,x6,8 <label>
4: 00a48433 add x8,x9,x10
00000008 <label>:
8: 00d605b3 add x11,x12,x13
jal
jal rd, offset //x[rd] = pc+4; pc += sext(offset)
跳轉並鏈接 (Jump and Link). J-type, RV32I and RV64I.
把下一條指令的地址(pc+4)保存到目的寄存器,然后把 pc 設置為當前值加上符號位擴展的offset。rd 默認為 x1。
壓縮形式: c.j offset; c.jal offset
imm | |||||||||||||||||||||||||||||||||
20 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 11 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | rd | opcode | ||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
jal | J | 1 | 1 | 0 | 1 | 1 | 1 | 1 |
例子:
00000000 <label-0x1c>:
0: 01430513 addi x10,x6,20
4: 01430593 addi x11,x6,20
8: 01430513 addi x10,x6,20
c: 01430513 addi x10,x6,20
10: 00c000ef jal x1,1c <label>
14: 01430613 addi x12,x6,20
18: 01430613 addi x12,x6,20
0000001c <label>:
1c: 01430613 addi x12,x6,20
20: 01430613 addi x12,x6,20
24: 01430613 addi x12,x6,20
注意:匯編和spec有點不一樣,匯編里面jal的立即數是絕對地址,但指令編碼是對的,偏移了12個字節,所以imm[3:1]=110,imm[0]默認為0。
00000004 <label>:
4: 01430593 addi x11,x6,20
8: 01430513 addi x10,x6,20
c: 01430513 addi x10,x6,20
10: ff5ff0ef jal x1,4 <label>
14: 01430613 addi x12,x6,20
18: 01430613 addi x12,x6,20
偏移 為-12,補碼表示
jalr
jalr rd, offset(rs1) // t =pc+4; pc=(x[rs1]+sext(offset))&~1; x[rd]=t
跳轉並寄存器鏈接 (Jump and Link Register). I-type, RV32I and RV64I.
把 pc 設置為 x[rs1] + sign-extend(offset),把計算出的地址的最低有效位設為 0,並將原 pc+4的值寫入 f[rd]。 rd 默認為 x1。
壓縮形式: c.jr rs1; c.jalr rs1
imm | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
jalr | I | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
例子:
00000000 <label-0x4>:
0: 01430513 addi x10,x6,20
00000004 <label>:
4: 01430593 addi x11,x6,20
8: 01430513 addi x10,x6,20
c: 01430513 addi x10,x6,20
10: ffc082e7 jalr x5,-4(x1)
14: 01430613 addi x12,x6,20
18: 01430613 addi x12,x6,20
00000000 <label-0x4>:
0: 01430513 addi x10,x6,20
00000004 <label>:
4: 01430593 addi x11,x6,20
8: 01430513 addi x10,x6,20
c: 01430513 addi x10,x6,20
10: 004082e7 jalr x5,4(x1)
14: 01430613 addi x12,x6,20
18: 01430613 addi x12,x6,20
4. 同步指令
fence
fence pred, succ //Fence(pred, succ)
同步內存和 I/O(Fence Memory and I/O). I-type, RV32I and RV64I.
在后續指令中的內存和 I/O 訪問對外部(例如其他線程)可見之前,使這條指令之前的內存及 I/O 訪問對外部可見。比特中的第 3,2,1 和 0 位分別對應於設備輸入,設備輸出,內存讀寫。例如 fence r, rw,將前面讀取與后面的讀取和寫入排序,使用 pred = 0010 和 succ = 0011進行編碼。如果省略了參數,則表示 fence iorw, iorw,即對所有訪存請求進行排序。
pred | succ | rs1 | func3 | rd | opcode | ||||||||||||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
fence | I | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
例子:
0: 0ff0000f fence iorw,iorw
Risc-V在多個hart(硬件線程)之間使用的是松散一致性模型,所以需要存儲器fence指令。
fence指令能夠保證存儲器訪問的執行順序。在fence指令之前的所有存儲器訪問指令,比該fence之后的所有數據存儲器訪問指令先執行。
Risc-V架構將數據存儲器的地址空間分為設備IO(device IO)和普通存儲器空間,因此其讀寫訪問分為四種類型:
I:設備讀(device-input)
O:設備寫(device-ouput)
R:存儲器讀(memory-reads)
W:存儲器寫(memory-writes)
PI/PO/PR/PW,分別表示fence指令之前的四種讀寫訪問類型,SI/SO/SR/SW分別表示fence指令之后的四種讀寫訪問類型。
6.環境調用和斷點指令
這兩條指令能夠產生環境調用異常和生成斷點異常,產生異常時候,當前指令的pc值被寫入mepc寄存器。
這兩條指令在調試代碼時候有用。
ecall
ecall //RaiseException(EnvironmentCall)
環境調用 (Environment Call). I-type, RV32I and RV64I.
通過引發環境調用異常來請求執行環境。
imm | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
ecall | I | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 |
例子:
0: 00000073 ecall
ebreak
Ebreak //RaiseException(Breakpoint)
環境斷點 (Environment Breakpoint). I-type, RV32I and RV64I.
通過拋出斷點異常的方式請求調試器。
imm | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1 | func3 | rd | opcode | ||||||||||||||||||
name | type | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
ebreak | I | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 |
例子:
0: 00100073 ebreak