RISC-V 速查表
本页面汇总了 RISC-V 编程中最常用的指令和知识点,方便快速查阅。
通用寄存器
| 寄存器 | ABI 名称 | 用途 | 保存者 |
|---|---|---|---|
| x0 | zero | 硬件零 | - |
| x1 | ra | 返回地址 | 调用者 |
| x2 | sp | 栈指针 | 被调用者 |
| x3 | gp | 全局指针 | - |
| x4 | tp | 线程指针 | - |
| x5-x7 | t0-t2 | 临时寄存器 | 调用者 |
| x8 | s0/fp | 保存寄存器/帧指针 | 被调用者 |
| x9 | s1 | 保存寄存器 | 被调用者 |
| x10-x11 | a0-a1 | 参数/返回值 | 调用者 |
| x12-x17 | a2-a7 | 参数 | 调用者 |
| x18-x27 | s2-s11 | 保存寄存器 | 被调用者 |
| x28-x31 | t3-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 寄存器
机器模式
| 地址 | 名称 | 描述 |
|---|---|---|
| 0x300 | mstatus | 机器状态 |
| 0x301 | misa | 机器 ISA |
| 0x304 | mie | 机器中断使能 |
| 0x305 | mtvec | 机器陷阱向量 |
| 0x340 | mscratch | 机器暂存 |
| 0x341 | mepc | 机器异常 PC |
| 0x342 | mcause | 机器异常原因 |
| 0x343 | mtval | 机器陷阱值 |
| 0x344 | mip | 机器中断挂起 |
监督模式
| 地址 | 名称 | 描述 |
|---|---|---|
| 0x100 | sstatus | 监督状态 |
| 0x104 | sie | 监督中断使能 |
| 0x105 | stvec | 监督陷阱向量 |
| 0x140 | sscratch | 监督暂存 |
| 0x141 | sepc | 监督异常 PC |
| 0x142 | scause | 监督异常原因 |
| 0x143 | stval | 监督陷阱值 |
| 0x144 | sip | 监督中断挂起 |
| 0x180 | satp | 监督地址翻译 |
用户模式
| 地址 | 名称 | 描述 |
|---|---|---|
| 0xC00 | cycle | 周期计数器 |
| 0xC01 | time | 时间计数器 |
| 0xC02 | instret | 指令计数器 |
异常和中断编码
异常编码
| 编码 | 名称 | 描述 |
|---|---|---|
| 0 | Instruction address misaligned | 指令地址未对齐 |
| 1 | Instruction access fault | 指令访问错误 |
| 2 | Illegal instruction | 非法指令 |
| 3 | Breakpoint | 断点 |
| 4 | Load address misaligned | 加载地址未对齐 |
| 5 | Load access fault | 加载访问错误 |
| 6 | Store/AMO address misaligned | 存储地址未对齐 |
| 7 | Store/AMO access fault | 存储访问错误 |
| 8 | Environment call from U-mode | 用户模式系统调用 |
| 9 | Environment call from S-mode | 监督模式系统调用 |
| 11 | Environment call from M-mode | 机器模式系统调用 |
| 12 | Instruction page fault | 指令页错误 |
| 13 | Load page fault | 加载页错误 |
| 15 | Store/AMO page fault | 存储页错误 |
中断编码
| 编码 | 名称 | 描述 |
|---|---|---|
| 1 | Supervisor software interrupt | 监督软件中断 |
| 3 | Machine software interrupt | 机器软件中断 |
| 5 | Supervisor timer interrupt | 监督定时器中断 |
| 7 | Machine timer interrupt | 机器定时器中断 |
| 9 | Supervisor external interrupt | 监督外部中断 |
| 11 | Machine 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|