RISC-V指令集学习

目录

前言

参考:

架构寻址:

RISC_V指令集扩展包括:

原子指令:

加载保留/条件存储:

原子内存操作(AMO):

压缩指令集RV32C:

浮点指令集:



前言

这篇文章只是简单的介绍了RISC-V的指令集,重点讲述原子指令,适合理论学习,感兴趣的读者还可以参考其他文章,内容难免存在疏漏还请指正。

参考:

开源RISC-V处理器架构分析与验证

架构寻址:

架构寻址方式有很多,但是常见的依旧是是如下几个:

  1. 基地址寻址:包含一个基址寄存器和一个12位的立即数偏移量,有效地址为基址寄存器的值+符号扩展后的偏移量。通常内存访问指令(LW,SW)的时候就是这种寻址。
  2. PC寻址:包含计数器和立即数,目标地址为当前计数器(PC)+指令中扩展后的偏移量。通常应用于条件分支和跳转指令。
  3. 寄存器寻址:指令中直接指定寄存器编号。
  4. 堆栈寻址:包含栈指针(sp),以sp为基址进行偏移访问,可以是字偏移(乘4偏移).
  5. 其他

RISC_V指令集扩展包括:

  1. M型指令集:整数乘除
  2. A型指令集:原子操作,也称为原子指令。
  3. C型指令集:压缩指令,其指令是16位。
  4. F型指令集:单精度浮点
  5. D型指令集:双精度浮点

下面讲述一下指令集,重点讲述的是A型指令集,它比较抽象。

M型指令集无非就是加减乘除与或非等运算,交给ALU执行单元或者乘法器除法器操作即可,相信大家很好理解。

原子指令:

指令集架构定义的原子指令有两种操作类型:

  1. 加载保留/条件存储操作(load reserved/ store conditional)
  2. 原子内存操作(atomic memory operation,简称AMO)

加载保留/条件存储:

指令类型

指令操作

指令描述

Lr.w  (加载保留)(32位)

Lr.d (加载保留)(64位)

Lr.w   rd    rs1

X(rd) = load_reserved(M(x(rsl)))

从内存地址为x(rs1)的位置加载4或8个字节,符号位扩展后写入x(rd),并对内存字注册保留

Sc.w  (条件存储)(32位置)

Sc.d (条件存储)(64位)

Sc.w   rd    rs2    rs1

X(rd) = store_conditional(M(x(rs1)),rs2))

将rs2寄存器的值写入存储器(存储器的地址为rs1的值),执行成功则向地址rd寄存器写入0,失败就写入错误码

字注册保留我并不是很懂,起的作用大概是将一部分内存注册或者记录保留状态,内核不会为它们创建页表,所以一般的应用程序无法访问这个内存,以确保不会被其他进程占用。

其操作过程如图所示:

对rs1地址保留标记是为了以便其他CPU核访问时能够确保数据同步或者数据比较,这个操作往往对应与条件存储操作对应,读者可以理解为为了后续的Sc指令验证前面的Lr指令是否成对。

条件存储操作之前,会先判断rs1内存地址是否设置了保留状态,如果设置了保留状态就把rs2寄存器的值写入rs1内存地址里,往目标寄存器rd写入0表示保存成功。

如果rs1没有设置保留状态就不保存,往目标寄存器写入1表示保存失败,也可以写入错误码。

不管有没有存储成功,Sc指令都会清除当前保留的保留标记,或者说清除保留状态。

所以这两个指令的操作配合为:

  1. 使用lr指令从内存中加载出旧值,并对这个地址设置保留状态。
  2. 比较旧值与新值(旧值是lr加载出来的,新值是sc要写入的)
  3. 如果旧值与新值相等,就把新值写入到lr标记的保留地址。
  4. 写入成功就把往目标寄存器写0,否则就写入1或者其他 代表错误的数值(非0)。
  5. 重试以上步骤,直到写入为止

可以看到原子指令中的加载保留和条件存储操作执行成功是有条件的,不成功会增加延时,成功条件为:

  1. lr 和 sc 指令要成对地访问同一个地址。
  2. 在 lr 和 sc 指令之间不能有其他指令访问过相同的地址(会导致保留状态失效)
  3. Lr 和 sc 指令之间不能有任何中断异常。
  4. Lr 和 sc 指令之间没有执行mret指令。

原子内存操作(AMO):

原子内存操作是从存储器(存储器地址为rs1的值)中读出数据存到寄存器rd中,并将它读出的数据与寄存器rs2的值进行运算,结果写入相同地址的存储器中(地址还是rs1)。

这个过程其实就是读——算——写的过程。

在读——写的过程间隙,存储器的地址同样不该被其他进程访问。

指令中的aq 和 rl可以理解为标签,这里不展示其指令格式了。

Aq (Acquire) 和 rl (release)都是原子操作的顺序标签,确保原子操作的顺序不会被打乱,具体来说,它们是标签。

Aq : 获取内存屏障,aq 的规则是确保原子操作后的内存操作不会重排序到原子操作之前。

Rl : 释放内存屏障,rl 的规则是确保原子操作后的内存操作不会重排序到原子操作之后。

内存重排序:CPU或者编译器自动调整内存访问指令的执行顺序的操作称为内存重排序。

压缩指令集RV32C:

压缩指令集并不是说是专门用来压缩操作的,压缩指令集是为了嵌入式应用程序提高代码密度而设计出的一套扩展指令,它可以添加到任何的基本ISA (指令架构上)。

压缩指令可以简单的看成是整数指令集的缩小简化版,其内部和整数指令集差别不带,并没有什么好说的,同样支持整数加减,数据存储,条件分支等。

值得一提的是压缩指令使用的是16位指令编码,不同于其他指令使用32位或 64位。

因此取指令的时候可能需要考虑指令重对齐。

浮点指令集:

浮点指令集扩展了32个32位宽的浮点寄存器f0~f31 和一个包含操作模式和浮点单元异常控制和状态寄存器fcsr。

其中的指令包含了浮点数的基本运算(加减移位)以及存储搬运等操作,并没什么特别的。

浮点指令集提供了整数寄存器的读写数值的指令,因此在浮点指令中可以实现格式转换。

  1. 浮点数与有符号整数的互相转换;
  2. 浮点数与无符号整数的互相转换;

特别的是,浮点指令集提供了符号注入指令,浮点分类指令,这些指令配合FPU浮点运算单元使用即可,详细可以参考更多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江流月照

感谢客官打赏与支持。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值