关于RISCV存储器访问指令的分析

RISC V 32I 指令访问存储器指令有load和STORE两类。这里说的load就是从存储器memory里面读出数据到寄存器组register files。而store正式相反的方向。

无论是load还是store我总结都有如下特点:

1,地址的生成都是一个寄存器的数值+一个立即数的偏移量(此立即数是有符号扩展)。

2,都是直接跟寄存器进行数据交换,也就是从寄存器到存储器不存在运算,都是直接拷贝进去。

我们知道,在C语言中可用的数据类型有字节,半字,和字。在32位的目标机中一般分别对应如下:

字节,BYTE 对应 unsigned char 或者char 

半字,HALF WORD 对应unsigned short 或者short

字, WORD 对应unsigned int 或者 int .

以上这三类是处理器最基本的处理的数据类型,所以RISCV 要分别实现对这三种数据类型load和store 。也因为这三种类型都要能寻址出来,所以地址应该用最小元素的地址单位,是字节地址。实际也是这样的,我们在存储器里说的地址都是字节地址。

我们先看store ,有三条指令  SB,SH,WORD,分别是store byte,Store Half word, Store Word .

Store Byte是将寄存器RS2的0位到7位内容保存在RS1为基地址,立即数进行有符号扩展后的S_IMM为偏移量(可正可负)的地址。

Store Half word 将寄存器RS2的0位到15位内容保存在RS1为基地址,立即数进行有符号扩展后的S_IMM为偏移量(可正可负)为开始两个字节的地址。这两个字节地址分别保存0为到7位,以及8-15位。这就有了大小字端的区别:如果0-7位保存在低字节地址,那么此存储方式就是小字段,反之为大字段。RISCV 支持的存储方式小字段,这和当下流行的INTEL 以及ARM 是一致的。

Store word 将寄存器RS2的0位到31位内容保存在RS1为基地址,立即数进行有符号扩展后的S_IMM为偏移量(可正可负)为开始四个字节的地址。当然也存在大小字端的说法,按照小字端方式存储。

这三条指令都是将某寄存器的内容里的某些位拷贝到指定的存储存储地址,而下面的这load指令就稍微复杂了点儿。

我们知道整数类型的数据都有signed 和unsigned 类型,也就是说有符号和无符号类型。而进行运算的寄存器类型都是32位,所以当从寄存器加载一个8位或者16位的数据的时候,就要区别这个数据是signed还是unsigned的,以便保存在32位寄存器里还是一个对应数值。

先回顾一下计算机实际表示负数的方法,基本我们所接触的系统表示整型负数都是用补码,一个负数的补码就是这个数对应整数的整数按位取反后加1。而看一个数是否为负数就看数据类型的最高位是否为1,  所以我们看char 类型的-1表示为 ~1+1 =8'HFF。而int类型的-1表示为 ~1+1 = 32'HFFFF_FFFF  。我要举的例子就是将一个char类型的字节 8'HFF 如果直接拷贝到32位寄存器的低8位,那么得到的数值按照32位的有符号整数或者32位无符号整数怎么解析都是32'H0000_00FF,是十进制的255,就不是-1了。怎么解决这个问题呢,就是加载这个8位数的时候首先要明确是否当做有符号数来加载,当做有符号数据加载就用LB  load byte 指令,而当做无符号数加载就用LBU load byte unsigned 来加载。LBU就是将字节简单的放在32位寄存器的低8位,其余高24位全部填0;而LB会先判断一下存储器字节的最高位是否1,如果是1就讲高24位全部填充为1,这样保持符号相同。所以我们如果将存储器里面的'HFF内容当做8位无符号整数(255)加载到寄存器就用LBU指令,在寄存器里面得到32'H0000_00FF这个结果,还是255;如果将存储器里面的'HFF内容当做8位有符号整数(-1)加载到寄存器就用LB指令,j加载时候进行符号位扩展(字节的最高位是1,所以32位寄存器的高24位都填写为1)在寄存器里面得到32'HFFFF_FFFF这个结果,这就是32位表示的有符号整数的-1。

我们这里不妨再较真一下,为了是LB 和LBU,是加载字节和加载无符号字节,这里应该是隐含了一层意思:LB除了加载有符号的字节整数,还可以加载无符号的字节整数?仔细想想,有符号字节可以表示正数,0和负数。而一个表示正数的有符号数进行位扩展实际也是将高24位填充为0,也就相当于实现了LBU,也就是实现了加载无符号字节,所以不能简单说这种为扩展指令就是Load Byte Signed。

上面分析了符号位扩展的必要性(保持正负号以及数值一致)和实现方式(可进行符号位扩展)。

 同样道理加载一个16位的半字,也就对应有了LH和LHU这两条指令。

加载一个32位的字,存储器里面保存的32位和处理器内通用寄存器保存的内容完全对应,因此不需要扩展,(也可以认为进行了扩展,只是最高符号位的扩展被忽略了),只有Load Word这条指令。而如果我们处理器执行的指令系统是64位的,也就是说寄存器是64位的,那么一个32位的存储器内容要加载到64位的寄存器里面同样面临是否进行位扩展的问题,这也就是为什么在64位指令系统里面多出了一个指令 LWU 。这么说来对应LW在64位寄存器的处理器实现要进行符号位扩展啦。

以上分析了RISCV32的存储相关指令。为了避免本篇内容太长,我在另外的BLOG再分析一下跟存储指令实现相关的内容。

 

 

有兴趣的朋友可以加QQ群一起学习讨论 29304866

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(RISCV,总结和计划)