最近尝试跟着 rCore Tutorial 教程,使用 Rust 实现基于 RISC-V 架构的类 Unix 内核,从而在深化 OS 理解的目标上,同时入门学习 Rust 语言和 RISC-V 基础。虽然说是 RISC-V 比 x86 简单很多,但是直接跟着教程来同时学习 RISC-V 还是有点不够,经常前面记得一点零星的汇编,看到后面的代码就忘了是怎么回事了。所以尝试来整理一下 RISC-V 的汇编,希望能让看到的小伙伴快速的入门一下。本文将以 64 位为例介绍汇编语言。
ISA 命令规范
命名格式: RV[###](abc…xyz)。
- RV: 用于标识 RISC-V 体系架构的前缀
- [###]: {32, 64, 128} 用于标识处理器的字宽,也就是处理器寄存器的宽度
- [abc…xyz]: 标识该处理器支持的指令集模块集合
举例: RV64I。意指 RISC-V 64 位实现,I 表示整数指令集。
对于 x86 体系架构,它的新一代处理器不仅实现了新的 ISA 扩展,还必须实现过去所有的扩展(最近宣布了要做 x86S),称之为“增量 ISA”。RISC-V 和传统的 x86 指令不一样,是“模块化 ISA”,由 1 个基本整数指令集 + 多个可选的扩展指令集组成。
指令集模块
基本整数 (Integer) 指令集
唯一强制要求实现的基础指令集,其他指令集都是可选的扩展模块
基本指令集 描述 RV32I 32 位整数指令集 RV32E RV32I 的子集,用于小型的嵌入式场景 RV64I 64 位整数指令集,兼容 RV32I RV128I 128 位整数指令集,兼容 RV64I 和 RV32I 扩展模块指令集
- RISC-V 允许可选的实现其他标准化和非标准化的指令集扩展
- 特定组合“IMAFD”被称为“通用 (General)”组合,用英文字母 G 表示
扩展指令集 描述 M 整数乘法 (Multiplication) 与除法指令集 A 存储器原子 (Atomic) 指令集 F 单精度 (32bit) 浮点指令集 D 双精度 (64bit) 浮点指令集 C 压缩 (Compressed) 指令集 … 其他标准和未标准化的指令集
寄存器
通用寄存器
Unprivileged Specification 定义了 32 个通用寄存器以及一个 PC。如果需要实现 F/D 扩展则需要额外支持 32 个浮点寄存器。RV32E 将 32 个通用寄存器缩减为 16 个。
寄存器宽度由 ISA 决定,RV32 的寄存器宽度为 32 位,RV64 的寄存器宽度为 64 位。
每个寄存器具体编程时有特定的用途以及各自的别名。由 RISC-V Application Binary Interface (ABI) 定义。
5-bit Encoding (rx) | 3-bit Compressed Encoding (rx') | Register | ABI Name | Description | Saved by Calle- |
---|---|---|---|---|---|
0 | - | x0 | zero | hardwired zero | - |
1 | - | x1 | ra | return address | -R |
2 | - | x2 | sp | stack pointer | -E |
3 | - | x3 | gp | global pointer | - |
4 | - | x4 | tp | thread pointer | - |
5 | - | x5 | t0 | temporary register 0 | -R |
6 | - | x6 | t1 | temporary register 1 | -R |
7 | - | x7 | t2 | temporary register 2 | -R |
8 | 0 | x8 | s0 / fp | saved register 0 / frame pointer | -E |
9 | 1 | x9 | s1 | saved register 1 | -E |
10 | 2 | x10 | a0 | function argument 0 / return value 0 | -R |
11 | 3 | x11 | a1 | function argument 1 / return value 1 | -R |
12 | 4 | x12 | a2 | function argument 2 | -R |
13 | 5 | x13 | a3 | function argument 3 | -R |
14 | 6 | x14 | a4 | function argument 4 | -R |
15 | 7 | x15 | a5 | function argument 5 | -R |
16 | - | x16 | a6 | function argument 6 | -R |
17 | - | x17 | a7 | function argument 7 | -R |
18 | - | x18 | s2 | saved register 2 | -E |
19 | - | x19 | s3 | saved register 3 | -E |
20 | - | x20 | s4 | saved register 4 | -E |
21 | - | x21 | s5 | saved register 5 | -E |
22 | - | x22 | s6 | saved register 6 | -E |
23 | - | x23 | s7 | saved register 7 | -E |
24 | - | x24 | s8 | saved register 8 | -E |
25 | - | x25 | s9 | saved register 9 | -E |
26 | - | x26 | s10 | saved register 10 | -E |
27 | - | x27 | s11 | saved register 11 | -E |
28 | - | x28 | t3 | temporary register 3 | -R |
29 | - | x29 | t4 | temporary register 4 | -R |
30 | - | x30 | t5 | temporary register 5 | -R |
31 | - | x31 | t6 | temporary register 6 | -R |
Control and Status Registers (CSR)
特权级介绍查看下文。这里仅介绍 Supervior 级别下的一些 CSR 寄存器,及其部分功能。其他详见 Spec。
不同的特权级别下,分别对应一套 Registers (CSR),用于控制不同特权级别下处理器的工作状态。
高特权级可以访问低级别的 CSR,反之不可以。
RISC-V 专门定义了操作 CSR 的指令。
Supervisor Trap Setup
Name | Description |
---|---|
sstatus | Supervisor status register 最重要的 CSR,可以从多个方面控制 S 特权级的 CPU 行为和执行状态。 SPP 等字段给出 Trap 发生之前 CPU 处于哪个特权级 (S/U) |
sedeleg | Supervisor exception delegation register 当 Trap 是一个异常的时候,记录 Trap 发生之前执行的最后一条指令地址。 |
sideleg | Supervisor interrupt delegation register |
sie | Supervisor interrupt-enable register |
stvec | Supervisor trap vector base address register 控制 Trap 处理代码的入口地址 |
scounteren | Supervisor counter enable register |
Supervisor Trap Handling
Name | Description |
---|---|
sscratch | Supervisor scratch register 一般用来存储内核栈的地址,在 trap 开始的地方与 sp 交换,从用户栈切换到内核栈 |
sepc | Supervisor exception program counter register |
scause | Supervisor trap cause register 描述 Trap 的原因 |
stval | Supervisor trap value register 给出 Trap 附加信息 |
sip | Supervisor interrupt pending register |
Supervisor Protection and Translation
Name | Description |
---|---|
satp | Supervisor address translation and protection |
其他概念
HART
HARdware Thread,简称为 HART。简单的可以理解为超线程。一个核心 (core) 可能会有多个 HART。
特权级别
RISC-V 架构中一共定义了 4 种特权级:
级别 | 编码 | 名称 |
---|---|---|
0 | 00 | 用户/应用模式 (U, User/Application) |
1 | 01 | 监督模式 (S, Supervisor) |
2 | 10 | 虚拟监督模式 (H, Hypervisor) |
3 | 11 | 机器模式 (M, Machine) |
级别的数值越大,特权级越高,。从表中可以看出, M 模式处在最高的特权级,而 U 模式处于最低的特权级。在CPU硬件层面,除了M模式必须存在外,其它模式可以不存在。
按需实现 RISC-V 特权级
RISC-V 架构中,只有 M 模式是必须实现的,剩下的特权级则可以根据跑在 CPU 上应用的实际需求进行调整:
- 简单的嵌入式应用只需要实现 M 模式;
- 带有一定保护能力的嵌入式系统需要实现 M/U 模式;
- 复杂的多任务系统则需要实现 M/S/U 模式。
汇编指令
编码格式
指令分类
指令详解
算术运算指令
逻辑运算指令
移位运算指令
内存读写指令
条件分支指令
无条件跳转指令
特权指令
csrrw rd, csr, rs
: 将 csr 当前值读到 rd,然后将 rs 的值写入该 csr