指令集和寄存器
1. 写在前面的话
本系列文章旨在通过十几个裸机程序开发逐渐熟悉RISCV架构,包括其重要的系统寄存器使用方式、中断和异常处理机制等等。本系列不是RISCV汇编语言教程,不会专门的讲解汇编语法,但是会对裸机程序中使用到的一些汇编进行简单的介绍,希望通过本系列文章的学习后,各位童鞋能掌握RISCV架构的基础知识,如果想进一步学习,可以阅读相关的开源软件源码或者查阅网络上相关RISCV资料。
2. RISCV模块化指令集设计
学习一个新的架构先来看看这个架构支持哪些指令,RISCV的指令集使用模块化的方式进行组织,每一个模块使用一个英文字母来表示。在指令集规范中,强制要求实现的是由字母I表示的基础整数指令集,其他指令集均为扩展可选,一般使用的扩展指令集包括M/A/F/D/C,如下所示。
以上模块的一个特定组合“IMAFD”,由于大多数RISCV处理器都会实现,所以也被称为通用组合,用英文字母G表示。因此RV32G表示RV32IMAFD,RV64G表示RV64IMAFD。
2.1 基础整数指令集
在RISCV架构中,除了压缩指令集外,其余的指令长度都为32位,也就是4个字节。整数指令集中的指令主要包括以下几类:
- 整数计算:主要是算术运算和逻辑运算类指令,实现加、减、与、或等功能计算。
- 地址访问:主要是Load和Store类指令,实现读写地址功能。
- 程序跳转:主要是分支跳转类和无条件跳转类指令,实现程序跳转功能。
- 控制状态:主要是系统控制状态寄存器访问类指令,实现对系统寄存器的访问。
2.2 扩展浮点指令集
RISCV的浮点扩展指令分为单精度和双精度两类,同时浮点指令使用单独的32个浮点寄存器,而不是通用整数寄存器,指令集功能主要包括以下几类:
- 算术运算:主要是加减乘除、矩阵计算、平方根、最大最小值等运算指令。
- 地址访问:主要是浮点寄存器Load和Store类指令,实现读写地址功能。
- 转换搬运:主要是整数和浮点类型数据转换、浮点和通用寄存器之间数据搬运指令。
2.3 扩展整数乘除指令集
这个扩展指令集主要实现对整数的乘法和除法运算,并支持有符号和无符号数。
2.4 扩展原子操作指令集
原子操作类指令主要用于保证对内存操作上的原子性, 原子表示内存读写之间的过程不会被打断,内存值也不会被其它处理器修改 。一般操作系统都会提供原子操作的系统API,其底层最终就是用这些原子操作指令来实现的。
2.5 扩展压缩指令集
RISCV通过压缩指令集可以提高代码密度,其作用类似于ARM中的 Thumb指令集,用于一些存储容量极度受限的嵌入式场景。
2.6 扩展向量指令集
类似于ARM下提供的NEON向量指令集,RISCV也提供了向量指令集扩展,用于单指令多数据(SIMD)操作。
2.7 其他扩展指令集
除了上述指令集外,还有若干的模块如L、B、P和T等,目前这些扩展大多数还在不断完善和定义中,尚未最终确定,因此不做详细阐述。
3. RISCV架构寄存器
3.1 32个通用寄存器
RISCV架构设计了32个通用整数寄存器和一个程序计数寄存器(PC),如下所示。
通用寄存器的长度在32位架构中为32位,在64位架构中为64位,下面介绍32个通用寄存器中比较重要的几个寄存器:
- x0:这个寄存器恒为0,读取的值永远为0。
- ra:用于保存函数调用返回地址,作用类似ARM架构中的lr寄存器。
- sp:用于保存栈地址,RISCV下和ARM下一样,一般使用满减栈方式。
- fp:用于保存栈帧,作用类似ARM下的bp寄存器。
- a0~a7:用于传递函数调用的参数,并且a0一般用于保存函数返回值。
3.2 32个浮点寄存器
当支持RISCV浮点扩展指令时,需要使用额外的32个浮点寄存器来支持浮点指令,如下所示。
3.2 控制状态寄存器
RISCV在M模式和S模式下分别具有一些控制状态寄存器,用于系统异常处理或者其他功能,至于什么是M模式和S模式会在下一章节进行讲解,这里以M模式为例,先介绍这个模式下的几个重要寄存器,S模式下的寄存器类似:
- mtvec(Machine Trap Vector):保存发生异常时处理器需要跳转的地址。
- mepc(Machine Exception PC):保存发生异常的指令地址。
- mcause(Machine Exception Cause):指明产生异常的原因。
- mie(Machine Interrupt Enable):指明处理器目前能处理和忽略的中断。
- mip(Machine Interrupt Pending):指明目前正准备处理的中断。
- mtval(Machine Trap Val):保存产生异常时的附加信息。
- mstatus(Machine Status):全局中断使能和其他状态信息。
评论