跳到主要内容

RISC-V 速查表

本页面汇总了 RISC-V 编程中最常用的指令和知识点,方便快速查阅。

通用寄存器​

寄存器ABI 名称用途保存者
x0zero硬件零-
x1ra返回地址调用者
x2sp栈指针被调用者
x3gp全局指针-
x4tp线程指针-
x5-x7t0-t2临时寄存器调用者
x8s0/fp保存寄存器/帧指针被调用者
x9s1保存寄存器被调用者
x10-x11a0-a1参数/返回值调用者
x12-x17a2-a7参数调用者
x18-x27s2-s11保存寄存器被调用者
x28-x31t3-t6临时寄存器调用者

基础整数指令​

算术运算​

add  rd, rs1, rs2    # rd = rs1 + rs2
addi rd, rs1, imm # rd = rs1 + imm
sub rd, rs1, rs2 # rd = rs1 - rs2
mul rd, rs1, rs2 # rd = rs1 * rs2(低32位)
mulh rd, rs1, rs2 # rd = (rs1 * rs2) >> 32(有符号)
div rd, rs1, rs2 # rd = rs1 / rs2(有符号)
rem rd, rs1, rs2 # rd = rs1 % rs2(有符号)

逻辑运算​

and  rd, rs1, rs2    # rd = rs1 & rs2
andi rd, rs1, imm # rd = rs1 & imm
or rd, rs1, rs2 # rd = rs1 | rs2
ori rd, rs1, imm # rd = rs1 | imm
xor rd, rs1, rs2 # rd = rs1 ^ rs2
xori rd, rs1, imm # rd = rs1 ^ imm

移位运算​

sll  rd, rs1, rs2    # rd = rs1 << rs2
slli rd, rs1, imm # rd = rs1 << imm
srl rd, rs1, rs2 # rd = rs1 >> rs2(逻辑)
srli rd, rs1, imm # rd = rs1 >> imm(逻辑)
sra rd, rs1, rs2 # rd = rs1 >> rs2(算术)
srai rd, rs1, imm # rd = rs1 >> imm(算术)

比较运算​

slt  rd, rs1, rs2    # rd = (rs1 < rs2) ? 1 : 0(有符号)
slti rd, rs1, imm # rd = (rs1 < imm) ? 1 : 0
sltu rd, rs1, rs2 # rd = (rs1 < rs2) ? 1 : 0(无符号)
sltiu rd, rs1, imm # rd = (rs1 < imm) ? 1 : 0(无符号)

加载存储​

lb  rd, offset(rs1)  # 加载字节(符号扩展)
lbu rd, offset(rs1) # 加载字节(零扩展)
lh rd, offset(rs1) # 加载半字(符号扩展)
lhu rd, offset(rs1) # 加载半字(零扩展)
lw rd, offset(rs1) # 加载字
ld rd, offset(rs1) # 加载双字(RV64)
sb rs2, offset(rs1) # 存储字节
sh rs2, offset(rs1) # 存储半字
sw rs2, offset(rs1) # 存储字
sd rs2, offset(rs1) # 存储双字(RV64)

分支指令​

beq  rs1, rs2, label  # if (rs1 == rs2) goto label
bne rs1, rs2, label # if (rs1 != rs2) goto label
blt rs1, rs2, label # if (rs1 < rs2) goto label(有符号)
bge rs1, rs2, label # if (rs1 >= rs2) goto label(有符号)
bltu rs1, rs2, label # if (rs1 < rs2) goto label(无符号)
bgeu rs1, rs2, label # if (rs1 >= rs2) goto label(无符号)

跳转指令​

jal  rd, label       # rd = pc + 4; pc = label
jalr rd, offset(rs1) # rd = pc + 4; pc = rs1 + offset

高位立即数​

lui   rd, imm        # rd = imm << 20
auipc rd, imm # rd = pc + (imm << 20)

常用伪指令​

li   rd, imm         # 加载立即数
la rd, label # 加载地址
mv rd, rs # 寄存器移动
nop # 空操作
not rd, rs # 按位取反
neg rd, rs # 取负
seqz rd, rs # rd = (rs == 0) ? 1 : 0
snez rd, rs # rd = (rs != 0) ? 1 : 0
j label # 无条件跳转
jr rs # 跳转到寄存器
ret # 返回
call function # 调用函数
tail function # 尾调用

CSR 指令​

csrrw  rd, csr, rs1  # 读 CSR 到 rd,写 rs1 到 CSR
csrrs rd, csr, rs1 # 读 CSR 到 rd,设置 CSR 位
csrrc rd, csr, rs1 # 读 CSR 到 rd,清除 CSR 位
csrr rd, csr # 读 CSR
csrw csr, rs1 # 写 CSR
csrs csr, rs1 # 设置 CSR 位
csrc csr, rs1 # 清除 CSR 位

常用 CSR 寄存器​

机器模式​

地址名称描述
0x300mstatus机器状态
0x301misa机器 ISA
0x304mie机器中断使能
0x305mtvec机器陷阱向量
0x340mscratch机器暂存
0x341mepc机器异常 PC
0x342mcause机器异常原因
0x343mtval机器陷阱值
0x344mip机器中断挂起

监督模式​

地址名称描述
0x100sstatus监督状态
0x104sie监督中断使能
0x105stvec监督陷阱向量
0x140sscratch监督暂存
0x141sepc监督异常 PC
0x142scause监督异常原因
0x143stval监督陷阱值
0x144sip监督中断挂起
0x180satp监督地址翻译

用户模式​

地址名称描述
0xC00cycle周期计数器
0xC01time时间计数器
0xC02instret指令计数器

异常和中断编码​

异常编码​

编码名称描述
0Instruction address misaligned指令地址未对齐
1Instruction access fault指令访问错误
2Illegal instruction非法指令
3Breakpoint断点
4Load address misaligned加载地址未对齐
5Load access fault加载访问错误
6Store/AMO address misaligned存储地址未对齐
7Store/AMO access fault存储访问错误
8Environment call from U-mode用户模式系统调用
9Environment call from S-mode监督模式系统调用
11Environment call from M-mode机器模式系统调用
12Instruction page fault指令页错误
13Load page fault加载页错误
15Store/AMO page fault存储页错误

中断编码​

编码名称描述
1Supervisor software interrupt监督软件中断
3Machine software interrupt机器软件中断
5Supervisor timer interrupt监督定时器中断
7Machine timer interrupt机器定时器中断
9Supervisor external interrupt监督外部中断
11Machine external interrupt机器外部中断

浮点指令(F/D 扩展)​

加载存储​

flw fd, offset(rs1)  # 加载单精度浮点
fld fd, offset(rs1) # 加载双精度浮点
fsw fs, offset(rs1) # 存储单精度浮点
fsd fs, offset(rs1) # 存储双精度浮点

算术运算​

fadd.s fd, fs1, fs2  # 单精度加法
fsub.s fd, fs1, fs2 # 单精度减法
fmul.s fd, fs1, fs2 # 单精度乘法
fdiv.s fd, fs1, fs2 # 单精度除法
fsqrt.s fd, fs1 # 单精度平方根

比较​

feq.s rd, fs1, fs2   # rd = (fs1 == fs2) ? 1 : 0
flt.s rd, fs1, fs2 # rd = (fs1 < fs2) ? 1 : 0
fle.s rd, fs1, fs2 # rd = (fs1 <= fs2) ? 1 : 0

转换​

fcvt.w.s rd, fs1     # 单精度转整数
fcvt.s.w fd, rs1 # 整数转单精度
fcvt.d.s fd, fs1 # 单精度转双精度
fcvt.s.d fd, fs1 # 双精度转单精度

原子指令(A 扩展)​

lr.w     rd, (rs1)        # 加载保留
sc.w rd, rs2, (rs1) # 存储条件
amoswap.w rd, rs2, (rs1) # 原子交换
amoadd.w rd, rs2, (rs1) # 原子加法
amoand.w rd, rs2, (rs1) # 原子与
amoor.w rd, rs2, (rs1) # 原子或
amoxor.w rd, rs2, (rs1) # 原子异或
amomin.w rd, rs2, (rs1) # 原子最小值
amomax.w rd, rs2, (rs1) # 原子最大值

压缩指令(C 扩展)​

c.li   rd, imm      # 加载立即数
c.lui rd, imm # 加载高位立即数
c.addi rd, imm # 加法立即数
c.add rd, rs # 加法
c.mv rd, rs # 移动
c.lw rd, offset(rs1) # 加载字
c.sw rs2, offset(rs1) # 存储字
c.beqz rs, label # 等于零分支
c.bnez rs, label # 不等于零分支
c.j label # 跳转
c.jr rs # 寄存器跳转
c.ret # 返回

调用约定​

参数传递​

  • 整数参数:a0-a7(x10-x17)
  • 浮点参数:fa0-fa7
  • 返回值:a0/a1 或 fa0/fa1
  • 超过 8 个参数通过栈传递

寄存器保存​

  • 调用者保存:t0-t6, a0-a7
  • 被调用者保存:s0-s11, ra, sp

常用代码模板​

函数序言/尾声​

function:
addi sp, sp, -16
sw ra, 12(sp)
sw s0, 8(sp)
# ...
lw s0, 8(sp)
lw ra, 12(sp)
addi sp, sp, 16
ret

自旋锁​

spin_lock:
lr.w t0, (a0)
bnez t0, spin_lock
sc.w t0, a1, (a0)
bnez t0, spin_lock
ret

系统调用​

# Linux 系统调用
li a7, syscall_number
ecall
# 返回值在 a0

指令格式​

R 型​

|31-25|24-20|19-15|14-12|11-7|6-0|
|funct7| rs2 | rs1 |funct3| rd |opcode|

I 型​

|31-20    |19-15|14-12|11-7|6-0|
|imm[11:0]| rs1 |funct3| rd |opcode|

S 型​

|31-25   |24-20|19-15|14-12|11-7   |6-0|
|imm[11:5]| rs2 | rs1 |funct3|imm[4:0]|opcode|

B 型​

|31-25       |24-20|19-15|14-12|11-7     |6-0|
|imm[12|10:5]| rs2 | rs1 |funct3|imm[4:1|11]|opcode|

U 型​

|31-12      |11-7|6-0|
|imm[31:12] | rd |opcode|

J 型​

|31-12              |11-7|6-0|
|imm[20|10:1|11|19:12]| rd |opcode|