皋陶 发表于 2020-8-24 10:56:16

RISC-V加载常量(立即数或地址)

本帖最后由 皋陶 于 2020-8-27 13:49 编辑


RISC-V使用I-type格式的指令和U-type格式的指令加载立即数,I-type格式包含12位立即数,U-type格式包含20位立即数,而且这20位是加载到寄存器的高20位的。
所以,一条I-type指令加上一条U-type指令就可以加载32位的常量,包括32位的立即数或内存地址。有些情况下只需要一条I-type指令,或者一条U-type指令就可以了。
mingdu.zheng at gmail dot com

I-type和U-type指令格式定义如下:



小常量

这里的小常量是指 -2048 ~ 2047 之间的常量,I-type格式的12位立即数是表示成有符号数的,所以其立即数能表示的范围就是 -2048 ~ 2047 ,这个范围内的小常量只需要使用一条 I-type指令就可以了,不需要额外的U-type指令。例如加载常量1234到寄存器x14:

addi      x14,x0,1234
低12位为零的32位常量这种常量值需要U-type指令,不需要额外的I-type指令,例如加载常量0x12345000:
lui                x14,0x12345

其它32位常量
除了上述两种特殊情况之外的其它32位常量,都需要I-type指令和U-type指令配合加载常量,例如加载常量0x12345678:
lui                x15,0x12345 # 首先加载常量的高20位
addi                x15,x15,0x678 # 再将低12位加到高20位

和 Cortex-M 对比
相比之下,Cortex-M 加载32位常量,通常要把常量存储在代码段,然后通过LDR指令从代码段读取。RISC-V加载32位常量使用2条指令,占用8个字节;Cortex-M加载常量使用1条指令和1条常量,占用6个字节或8个字节(有16位长的LDR指令,也有32位长的LDR指令)。RISC-V使用2条指令,只需要访问指令总线,没有存储器加载的延时和总线冲突,Cortex-M因为要从代码段加载,既要访问指令总线也要访问数据总线,会有存储器加载延时和可能的总线冲突。
RV32 加载64位常量
在RV32架构下,需要两个寄存器来存储64位数,理论上讲可以使用两组I-type和U-type组合就可以加载64位常量,例如加载常量0x1234567812345678:# 低32位存储在x14
lui                x14,0x12345
addi                x14,x14,0x678
# 高32位存储在x15
lui                x15,0x12345
addi                x15,x15,0x678
但是,目前GCC给出的编译结果如下:
lui                x14,0x8000
lw                x12,0(x14)
lw                x13,4(x14)
首先把64位常量存储在代码段,然后使用lw指令加载。
RV64 加载64位常量
也是先把64位常量存储在代码段,然后使用ld指令加载,RV64使用1个寄存器就可以存储64位数了,所以这回只需要加载一次:
lui                x14,0x8000
ld                x14,0(x14)本篇完,感谢关注:RISC-V单片机中文网
页: [1]
查看完整版本: RISC-V加载常量(立即数或地址)