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

版权声明:本文为博主原创文章,转载请保持文章完整,保留作者信息。 https://blog.csdn.net/zoomdy/article/details/83067689

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
https://blog.csdn.net/zoomdy/article/details/83067689

I-typeU-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-typeU-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)

猜你喜欢

转载自blog.csdn.net/zoomdy/article/details/83067689