6.S081 学习笔记 - Lab-Traps

RISC-V 知识点

RISC-V 寄存器

RISC-V寄存器
RISC-V 寄存器

从表中可以看到,保存寄存器和临时寄存器的编号不是连续的。这是为了支持另一个只有 16 个寄存器的 RISC-V 变种 RV32E。

保存寄存器和栈指针在函数调用前后保持不变,它们的值由被调用者保存和恢复。

临时寄存器、函数参数和返回值在函数调用前后可能会被修改,它们的值由调用者保存和恢复。

关于调用前后是否一致可以这样理解:保存寄存器一般是存一些重要的值,而临时寄存器是存一些不重要的中间结果或临时值。所以被调用者 (Callee) 如果要利用保存寄存器的空间就需要负责在使用后恢复原样,而对临时寄存器无需负责 (因为它认为临时寄存器中的值不重要)。因此如果调用者 (Caller) 在临时寄存器中保存了在函数调用后还需要的值,它就需要自己负责保存,避免被被调用者修改。

32 位和 64 位 RISC-V 的寄存器数量相同,只是寄存器的位宽不同。

RV32I 指令集

RV32I指令集概览
RV32I 指令集概览

指令分类

  • R 型:用于寄存器之间的操作
  • I 型:用于短立即数和寄存器之间的操作
  • S 型:用于存储操作
  • B 型:用于条件分支操作
  • U 型:用于长立即数的操作
  • J 型:用于无条件跳转操作

指令列表

整数计算指令

指令名称 指令格式 描述
add add rd, rs1, rs2 x[rs2]x[rs1] 相加,结果存入 x[rd]
addi addi rd, rs1, imm imm 符号扩展后与 x[rs1] 相加,结果存入 x[rd]
sub sub rd, rs1, rs2 x[rs1] 减去 x[rs2],结果存入 x[rd]
and and rd, rs1, rs2 x[rs1]x[rs2] 按位与,结果存入 x[rd]
andi andi rd, rs1, imm imm 符号扩展后和 x[rs1] 按位与,结果存入 x[rd]
or or rd, rs1, rs2 x[rs1]x[rs2] 按位或,结果存入 x[rd]
ori ori rd, rs1, imm imm 符号扩展后和 x[rs1] 按位或,结果存入 x[rd]
xor xor rd, rs1, rs2 x[rs1]x[rs2] 按位异或,结果存入 x[rd]
xori xori rd, rs1, imm imm 符号扩展后和 x[rs1] 按位异或,结果存入 x[rd]
sll sll rd, rs1, rs2 x[rs1] 逻辑左移 x[rs2] 位,结果存入 x[rd]x[rs2] 的低 5 位是移位位数,高位忽略
slli slli rd, rs1, shamt x[rs1] 逻辑左移 shamt 位,结果存入 x[rd]。仅当 shamt[5]=0 时指令合法
srl srl rd, rs1, rs2 x[rs1] 逻辑右移 x[rs2] 位,结果存入 x[rd]x[rs2] 的低 5 位是移位位数,高位忽略
srli srli rd, rs1, shamt x[rs1] 逻辑右移 shamt 位,结果存入 x[rd]。仅当 shamt[5]=0 时指令合法
sra sra rd, rs1, rs2 x[rs1] 算术右移 x[rs2] 位,结果存入 x[rd]x[rs2] 的低 5 位是移位位数,高位忽略
srai srai rd, rs1, shamt x[rs1] 算术右移 shamt 位,结果存入 x[rd]。仅当 shamt[5]=0 时指令合法
lui lui rd, imm 将 20 位 imm 符号扩展后左移 12 位,低 12 位置 0,结果存入 x[rd]
auipc auipc rd, imm 将 20 位 imm 符号扩展后左移 12 位,加上 pc,结果存入 x[rd]
slt slt rd, rs1, rs2 如果 x[rs1] 小于 x[rs2],则 x[rd]=1,否则 x[rd]=0
slti slti rd, rs1, imm 如果 x[rs1] 小于符号扩展后的 imm,则 x[rd]=1,否则 x[rd]=0
sltiu sltiu rd, rs1, imm 如果 x[rs1] 小于无符号扩展后的 imm(视为无符号数),则 x[rd]=1,否则 x[rd]=0

控制转移指令

指令名称 指令格式 描述
beq beq rs1, rs2, offset 如果 x[rs1] 等于 x[rs2],则将 pc 设为当前值加上符号扩展后的 offset
bne bne rs1, rs2, offset 如果 x[rs1] 不等于 x[rs2],则将 pc 设为当前值加上符号扩展后的 offset
bge bge rs1, rs2, offset 如果 x[rs1] 大于等于 x[rs2],则将 pc 设为当前值加上符号扩展后的 offset
bgeu bgeu rs1, rs2, offset 如果 x[rs1] 大于等于 x[rs2](视为无符号数),则将 pc 设为当前值加上符号扩展后的 offset
blt blt rs1, rs2, offset 如果 x[rs1] 小于 x[rs2],则将 pc 设为当前值加上符号扩展后的 offset
bltu bltu rs1, rs2, offset 如果 x[rs1] 小于 x[rs2](视为无符号数),则将 pc 设为当前值加上符号扩展后的 offset
jal jal rd, offset 将下一条指令的地址 (pc+4) 写入 x[rd],然后将 pc 设为当前值加上符号扩展后的 offset。若省略 rd,则默认为 x1
jalr jalr rd, rs1, imm pc 设为 x[rs1]+sign-extend(offset),将跳转地址的最低位清零,并将原 pc+4 写入 x[rd]。若省略 rd,则默认为 x1

装载存储指令

指令名称 指令格式 描述
lb lb rd, offset(rs1) x[rs1]+sign-extend(offset) 读取一个字节,符号扩展后存入 x[rd]
lbu lbu rd, offset(rs1) x[rs1]+sign-extend(offset) 读取一个字节,零扩展后存入 x[rd]
lh lh rd, offset(rs1) x[rs1]+sign-extend(offset) 读取两个字节,符号扩展后存入 x[rd]
lhu lhu rd, offset(rs1) x[rs1]+sign-extend(offset) 读取两个字节,零扩展后存入 x[rd]
lw lw rd, offset(rs1) x[rs1]+sign-extend(offset) 读取四个字节,符号扩展后存入 x[rd]
sb sb rs2, offset(rs1) x[rs2] 的最低字节存入内存地址 x[rs1]+sign-extend(offset)
sh sh rs2, offset(rs1) x[rs2] 的最低 2 字节存入内存地址 x[rs1]+sign-extend(offset)
sw sw rs2, offset(rs1) x[rs2] 的最低 4 字节存入内存地址 x[rs1]+sign-extend(offset)

其他指令

指令名称 指令格式 描述
fence fence pred, succ 内存屏障,保证内存操作的顺序性
fence.i fence.i 指令屏障,保证指令的顺序性
ebreak ebreak 通过抛出断点异常调用调试器
ecall ecall 通过抛出环境调用异常调用执行环境
csrrc csrrc rd, csr, rs1 记控制状态寄存器 csr 的值为 t。将 x[rs1] 的反码和 t 按位与,结果写入 csr,再将 t 写入 x[rd]
csrrci csrrci rd, csr, zimm[4:0] 记控制状态寄存器 csr 的值为 t。将 5 位立即数 zimm 零扩展后的反码和 t 按位与,结果写入 csr,再将 t 写入 x[rd]
csrrs csrrs rd, csr, rs1 记控制状态寄存器 csr 的值为 t。将 x[rs1] 的值和 t 按位或,结果写入 csr,再将 t 写入 x[rd]
csrrsi csrrsi rd, csr, zimm[4:0] 记控制状态寄存器 csr 的值为 t。将 5 位立即数 zimm 零扩展后的值和 t 按位或,结果写入 csr,再将 t 写入 x[rd]
csrrw csrrw rd, csr, rs1 记控制状态寄存器 csr 的值为 t。将 x[rs1] 的值写入 csr,再将 t 写入 x[rd]
csrrwi csrrwi rd, csr, zimm[4:0] 将控制状态寄存器的值复制到 x[rd],再将 5 位立即数 zimm 零扩展后的值写入 csr

RV64I 指令集

RV64I指令集
RV64I 指令集

在 RV32I 的基础上,RV64I 增加了图中红色的指令,主要是对字长的扩展。

RV32/RV64 特权架构

RV32/RV64特权指令集
RV32/RV64 特权指令集

特权模式下的异常处理

重要寄存器:

  • sstatus(Supervisor Status):维护各种状态,其中 SIE 位控制设置中断使能,SPP 位存储异常发生的特权模式
  • sip(Supervisor Interrupt Pending):记录当前的中断请求
  • sie(Supervisor Interrupt Enable):维护处理器的中断使能状态
  • scause(Supervisor Exception Cause):指示发生了何种异常
  • stvec(Supervisor Trap Vector):指向异常处理程序的入口地址
  • stval(Supervisor Trap Value):存放当前自陷的额外信息
  • sepc(Supervisor Exception Program Counter):指向发生异常的指令地址
  • sscratch(Supervisor Scratch):向异常处理程序提供一个字的临时存储

处理流程:

  • 将发生异常的指令 PC 存入 sepc, 并将 PC 设为 stvec
  • 将异常原因写入 scause,并将故障地址或其他异常相关信息字写入 stval
  • sstatus.SIE 置零以屏蔽中断,并将 SIE 的旧值存放在 SPIE
  • 将异常发生前的特权模式存放在 sstatus.SPP,并将当前特权模式设为 S
  • sret 指令将 spec 的值复制到 PC

RISC-V 汇编器指示符

RISC-V汇编器指示符
RISC-V 汇编器指示符

不用中间变量交换两个整数的值

1
2
3
4
5
6
int a = 1;
int b = 2;
a = a ^ b; // (1)
b = a ^ b; // (2)
a = a ^ b; // (3)
// a = 2, b = 1

异或运算的性质:

  • 交换律:\(a \oplus b = b \oplus a\)
  • 结合律:\((a \oplus b) \oplus c = a \oplus (b \oplus c)\)
  • 逆元:\(a \oplus a = 0\)
  • 单位元:\(a \oplus 0 = a\)

证明:

将 (1) 代入 (2):\(b = (a \oplus b) \oplus b = a \oplus (b \oplus b) = a \oplus 0 = a\)

将 (1) 和 (2) 代入 (3):\(a = (a \oplus b) \oplus a = b \oplus (a \oplus a) = b \oplus 0 = b\)

参考资料

《RISC-V 开放架构设计之道》


6.S081 学习笔记 - Lab-Traps
http://blog.qzink.me/posts/6.S081学习笔记-Lab-Traps/
作者
Qzink
发布于
2025年1月15日
许可协议