Riscv中每個硬件線程(hart)有4096個獨立地址空間的狀態寄存器。我們可以通過Zicsr指令讀寫csr寄存器。總共有6條csr讀寫指令,這些指令之前都在RV32I/RV64I基礎指令集里面,在最新文檔中,被放在了Zicsr擴展指令集中。
6條指令的編碼如下,其中[31-20]總共12位表示4096個csr寄存器地址。
csr | |||||||||||||||||||||||||||||||||
11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | rs1/imm | 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 |
csrrw | I | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | ||||||||||||||||||||||
csrrs | I | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | ||||||||||||||||||||||
csrrc | I | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | ||||||||||||||||||||||
csrrwi | I | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | ||||||||||||||||||||||
csrrsi | I | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | ||||||||||||||||||||||
csrrci | I | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 |
csr指令讀寫csr寄存器都是原子操作。
- 對於csrrw和csrwi,如果rd索引值為0,csr指令將不會發起csr寄存器的讀操作,也不會帶來任何讀操作的副作用。
- 對於csrrs和csrrc指令而言,如果rs1的索引值為0,csr指令將不會發起csr寄存器的寫操作,也不會帶來任何寫操作的副作用。
- 對於csrrsi和csrrci指令而言,如果立即數的索引值為0,csr指令將不會發起csr寄存器的寫操作,也不會帶來任何寫操作的副作用。
下面介紹這六條指令的功能:
csrrw
csrrw rd, csr, zimm[4:0] //t = CSRs[csr]; CSRs[csr] = x[rs1]; x[rd] = t
讀后寫控制狀態寄存器 (Control and Status Register Read and Write). I-type, RV32I and RV64I.
記控制狀態寄存器 csr 中的值為 t。 把寄存器 x[rs1]的值寫入 csr,再把 t 寫入 x[rd]。
例子:
to do
csrrs
csrrs rd, csr, rs1 //t = CSRs[csr]; CSRs[csr] = t | x[rs1]; x[rd] = t
讀后置位控制狀態寄存器 (Control and Status Register Read and Set). I-type, RV32I and RV64I.
記控制狀態寄存器 csr 中的值為 t。 把 t 和寄存器 x[rs1]按位或的結果寫入 csr,再把 t 寫入x[rd]。
例子:
to do
csrrc
csrrc rd, csr, rs1 //t = CSRs[csr]; CSRs[csr] = t &~x[rs1]; x[rd] = t
讀后清除控制狀態寄存器 (Control and Status Register Read and Clear). I-type, RV32I andRV64I.
記控制狀態寄存器 csr 中的值為 t。 把 t 和寄存器 x[rs1]按位與的結果寫入 csr,再把 t 寫入x[rd]
例子:
to do
csrrwi
csrrwi rd, csr, zimm[4:0] //x[rd] = CSRs[csr]; CSRs[csr] = zimm
立即數讀后寫控制狀態寄存器 (Control and Status Register Read and Write Immediate). I-type,RV32I and RV64I.
把控制狀態寄存器 csr 中的值拷貝到 x[rd]中,再把五位的零擴展的立即數 zimm 的值寫入csr。
例子:
to do
csrrsi
csrrsi rd, csr, zimm[4:0] //t = CSRs[csr]; CSRs[csr] = t | zimm; x[rd] = t
立即數讀后設置控制狀態寄存器 (Control and Status Register Read and Set Immediate). I-type,RV32I and RV64I.
記控制狀態寄存器 csr 中的值為 t。 把 t 和五位的零擴展的立即數 zimm 按位或的結果寫入csr,再把 t 寫入 x[rd](csr 寄存器的第 5 位及更高位不變)。
例子:
to do
csrrci
csrrci rd, csr, zimm[4:0] //t = CSRs[csr]; CSRs[csr] = t &~zimm; x[rd] = t
立即數讀后清除控制狀態寄存器 (Control and Status Register Read and Clear Immediate). Itype, RV32I and RV64I.
記控制狀態寄存器 csr 中的值為 t。 把 t 和五位的零擴展的立即數 zimm 按位與的結果寫入csr,再把 t 寫入 x[rd](csr 寄存器的第 5 位及更高位不變)。
例子:
to do
下面是一些常用的csr偽指令:
rdinstret[h] rd | csrrs rd,instret[h],x0 | 讀取過時指令計數器 |
rdcycle[h] rd | csrrs rd,cycle[h],x1 | 讀取時鍾周期計數器 |
rdtime[h] rd | csrrs rd,time[h],x2 | 讀取實時時鍾 |
csrr rd, csr | csrrs rd, csr,x0 | 讀csr寄存器 |
csrw csr,rs | csrrw x0,csr,rs | 寫csr寄存器 |
csrs csr,rs | csrrs x0,csr,rs | csr寄存器置位0 |
csrc csr,rs | csrrc x0,csr,rs | csr寄存器清0 |
csrwi csr,imm | csrrwi x0,csr,imm | 立即數寫csr |
csrsi csr,imm | csrrsi x1,csr,imm | 立即數置位csr |
csrci csr,imm | csrrci x2,csr,imm | 立即數復位csr |
frcsr rd | csrrs rd,frm,x0 | 讀取fp舍入模式 |
fscsr rs | csrrw x0,frm,rs | 寫入fp舍入模式 |
frflags rd | csrrs rd,fflags,x0 | 讀取fp異常模式 |
fsflags rs | csrrw x0,fflags,rs | 寫入fp異常模式 |
fscsr rd,rs | csrrw rd,fcsr,rs | 交換fp控制狀態寄存器 |
fsrm rd,rs | csrrw rd,frm,rs | 交換fp舍入模式 |
fsflags rd,rs | csrrw,rd,fflags,rs | 交換fp異常標志 |