跳到主要内容

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|