RISC-V
RISC-V是一个通用的指令集架构(ISA),类似于一个标准,当硬件和软件分别遵循RISC-V标准时,就能无缝衔接,至于硬件后面是否有芯片解码,那就是商业化硬件自身的问题了(例如Type-C是一个开放性的标准接口,但是有些厂商会在使用时封装一层,达到商业化的目的)。
-
与ARM的不同
ARM是增量式的ISA,因为向前兼容问题,ARM的指令集已经很大。而RISC-V是模块化的,核心是RV32I的指令集,其他扩展模块可通过附加的方式进行扩展。例如:基本的是RV32I,当添加乘法(RV32M)后则表示为RV32IM。添加单精度(RV32F)和双精度(RV32D)时,表示为RV32FD,依次类推。
-
ISA设计衡量的标准
- 成本
- 简洁性
- 性能
- 架构和具体实现的分离
- 提升空间
- 程序大小
- 易于编程
-
指令集一览
RV32I 基础指令集
-
六种基本指令
- 用于寄存器-寄存器操作的 R 类型指令
- 用 于短立即数和访存 load 操作的 I 型指令
- 用于访存 store 操作的 S 型指令
- 用于条件跳转操 作的 B 类型指令,
- 用于长立即数的 U 型指令
- 用于无条件跳转的 J 型指令
-
RISC-V的指令格式,以基本指令为例
-
汇编与RISC-V的对应关系
指令 说明 汇编语言 RISC-V指令 add x9, x20, x21 x9=x20+x21 机器语言 十进制表示 0 21 20 0 9 51 0 0 和 51 表示执行加法操作,21表示寄存器编号(21表示x21),20表示另一个源操作数,9表示接收总和的寄存器编 机器语言 二进制-R型 0000000 7位 10101 5位 10100 5位 000 3位 01001 5位 0110011 7位 指令格式,共32位 R型-寄存器 二进制说明 funct7 操作码字段 rs2 原操作寄存器 rs1 源操作数寄存器 funct3 操作码字段 rd 目标操作数寄存器 opcode 操作码 I型-常数 二进制-I型 immediate 12位 rs1 5位 funct3 3位 rd 5位 opcode 7位 举例addi S型-基址和存储数据 二进制-S型 immediate 7位 rs2 5位 rs1 5位 funct3 3位 immediate 位 opcode 7位 ld x9, 64(x22)
-
-
C语言与汇编说明
-
RISC-V寄存器 共32个寄存器
名称 寄存器号 用途 接口名称 是否保留 x0 0 常数0 zero x1 1 返回赋值 ra 不保留 x2 2 栈指针 sp 保留 x3 3 全局指针 gp x4 4 线程指针 tp x5 5 临时,备用链接寄存器 t0 不保留 x6~x7 6~7 临时寄存器 t1 t2 不保留 x8 8 保存,帧指针 s0/fp 保留 x9 9 保存 s1 保留 x10~x11 10~11 函数参数、返回值 a0,a1 不保留 x12~x17 12~17 函数参数 a2-7 不保留 x18~x27 18~27 保存寄存器 s2-11 保留 x27~x31 27~31 临时寄存器 t3-6 不保留 -
各寄存器情况
保存 不保存 保存寄存器:x8, x9, x18~x27 临时寄存器:x5~x7, x28~x31 栈指针寄存器:x2(sp) 参数/结果寄存器:x10~x17 帧指针:x8(fp) 返回地址:x1(ra) 栈指针以上的栈 栈指针一下的栈
-
RISC-V汇编语言
-
函数调用规范
- 将参数存储到函数能够访问到的位置;
- 跳转到函数开始位置(使用 RV32I 的 jal 指令)
- 获取函数需要的局部存储资源,按需保存寄存器;
- 执行函数中的指令;
- 将返回值存储到调用者能够访问到的位置,恢复寄存器,释放局部存储资源;
- 返回调用函数的位置(使用 ret 指令)。
-
RISC-V函数入口及出口
# 入口 entry_label: addi sp, sp, -framesize # 调整栈指针(sp 寄存器)分配栈帧 sw ra, framesize-4(sp) #保存返回地址(ra 寄存器) # 出口 lw ra, framesize-4(sp) # 恢复返回地址 addi sp, sp, framesize # 释放栈帧空间 ret # 返回调用点
-
汇编器
-
指示符
-
RV32M:乘法和除法指令
RV32F 和 RV32D:单/双精度指令
RV32I中寄存器x0是常量,而f0则与其他寄存器一样,是可变寄存器。
RV32A:原子指令
-
内存原子操作
对内存中的操作数执行一个原子操作,并将目标寄存器设置为操作前的内存 值。原子表示内存读写之间的过程不会被打断,内存值也不会被其它处理器修改。- 类似于多线程中的原子值
-
加载保留/条件存储
加载保留读取一个内存 字,存入目标寄存器中,并留下这个字的保留记录。
RV32C:压缩指令
每条短指令必须和一条标准的 32 位 RISC-V 指令一一 对应
-
压缩指令原则
1.对十个常用寄存器(a0-a5,s0-s1,sp 以及 ra)访问的频率远超过其他寄存器;
2.许多指令的写入目标是它的源操作数之一;
3.立即数往往很小,而且有些指令比 较喜欢某些特定的立即数
-
举例
# 举例1 addi a4, x0, 1 # i=1 # 使用16位指令为: c.li a4, 1 # i=1 # 举例2 # a2是指向a[j]的指针 add a2, x0, a3 # 使用16位指令为: c.mv a2, a3
RV32V:向量
-
将向量的长度和每个时钟周期可以进行的最大操作数分 离,是向量体系结构的关键所在:向量微架构可以灵活地设计数据并行硬件而不会影响到 程序员,程序员可以不用重写代码就享受到长向量带来的好处。
-
寄存器以v开头,每个向量寄存器的元素个数不同,主要取决于处理器的设计者。