后端Corner case
ld/sd
的建议
对于可以等全部的ASM语句生成后,进行写一个打补丁的函数,检查所有的ld/sd
有没有超出范围。
addi
、xori
、ori
、andi
的建议
对于当这些指令的imm12
超过12位时[-2048, 2047],不建议使用打补丁的方式,而是生成时进行if-else
特殊判断,把imm12
放到寄存器里面,把对应的指令改成两个寄存器进行运算的格式,从而抛弃imm12
。
在RISC-V架构中,addi
、xori
、ori
、andi
这些指令的立即数(imm12
)都被限制为12位有符号整数,即范围为 -2048
到 2047
。如果立即数超过了这个范围,或者是一个浮点数,需要使用其他指令进行分解和处理。这里提供一些常见的处理方法。
立即数超过12位范围
当立即数超过12位范围时,可以使用 LUI
(Load Upper Immediate)指令加载高位部分,然后结合其他指令处理低位部分。下面是一些例子:
addi
例子
假设我们需要执行 addi x1, x2, 0x12345
:
LUI x3, 0x123 # 加载高位部分 0x123 << 12 到 x3
ADDI x3, x3, 0x45 # 加载低位部分 0x45 到 x3, 现在 x3 = 0x12345
ADD x1, x2, x3 # 将 x2 和 x3 相加,结果存储到 x1
xori
例子
假设我们需要执行 xori x1, x2, 0x12345
:
LUI x3, 0x123 # 加载高位部分 0x123 << 12 到 x3
ADDI x3, x3, 0x45 # 加载低位部分 0x45 到 x3, 现在 x3 = 0x12345
XOR x1, x2, x3 # 将 x2 和 x3 进行按位异或,结果存储到 x1
ori
例子
假设我们需要执行 ori x1, x2, 0x12345
:
LUI x3, 0x123 # 加载高位部分 0x123 << 12 到 x3
ADDI x3, x3, 0x45 # 加载低位部分 0x45 到 x3, 现在 x3 = 0x12345
OR x1, x2, x3 # 将 x2 和 x3 进行按位或,结果存储到 x1
andi
例子
假设我们需要执行 andi x1, x2, 0x12345
:
LUI x3, 0x123 # 加载高位部分 0x123 << 12 到 x3
ADDI x3, x3, 0x45 # 加载低位部分 0x45 到 x3, 现在 x3 = 0x12345
AND x1, x2, x3 # 将 x2 和 x3 进行按位与,结果存储到 x1
立即数是浮点数
对于浮点数,需要使用浮点寄存器和浮点指令。首先将浮点数加载到浮点寄存器中,然后进行相应的浮点运算。假设我们需要对浮点数进行加法(fadd.s
)、按位异或(feq.s
)、按位或(无直接指令,但可以通过其他方式实现)、按位与(无直接指令,但可以通过其他方式实现)操作。
加载浮点数到浮点寄存器
假设浮点数是 2.5
,使用 flw
(浮点加载字)指令加载浮点数到浮点寄存器:
# 将浮点数 2.5 加载到寄存器 f1
lui t0, %hi(float_val) # 加载浮点数地址的高位
addi t0, t0, %lo(float_val) # 加载浮点数地址的低位
flw f1, 0(t0) # 从内存中加载浮点数到寄存器 f1
# .data 段声明浮点数
.section .data
.align 2
float_val:
.float 2.5
fadd.s
例子
假设我们需要执行 fadd.s f2, f1, 2.5
:
# 将浮点数 2.5 加载到寄存器 f3
lui t0, %hi(float_val) # 加载浮点数地址的高位
addi t0, t0, %lo(float_val) # 加载浮点数地址的低位
flw f3, 0(t0) # 从内存中加载浮点数到寄存器 f3
# 执行浮点加法
fadd.s f2, f1, f3
总结
- 对于立即数超过12位的情况,可以使用
LUI
指令加载高位部分,并结合其他指令进行处理。 - 对于浮点数,需要使用浮点指令和浮点寄存器来加载和操作浮点数。
这样处理可以确保在RISC-V架构中正确地执行复杂的立即数和浮点数操作。