LUI(立即加载上限)用于构建32位常量,并使用U型格式。LUI将U中间值放在目标寄存器rd的高20位中,并用零填充最低12位。
我在手册中找到了这个,但是如果我想将0xffffffff移到寄存器中,我需要的所有代码是:
LUI x2, 0xfffff000
ADDI x2, x2, 0xfff
Run Code Online (Sandbox Code Playgroud)
但是发生了一个问题,ADDI将扩展符号以使立即数据成为带符号的数字,因此0xfff将扩展到0xffffffff。
这使x2以0xffffefff,但不0xffffffff
什么是立即移动32位进行注册的良好实现?
RISC-V汇编程序支持伪指令li x2, 0xFFFFFFFF。
Let N是一个带符号的2的补码32位整数。
的常见实现li x2,N是:
# sign extend low 12 bits
M=(N << 20) >> 20
# Upper 20 bits
K=((N-M) >> 12) <<12
# Load upper 20 bits
LUI x2,K
# Add lower bits
ADDI x2,x2,M
Run Code Online (Sandbox Code Playgroud)
当然,要加载短即时li即可使用
addi x2,x0,imm
Run Code Online (Sandbox Code Playgroud)
所以li x2, 0xFFFFFFFF是addi x2,x0,-1。
TL; DR:你要加载的32位常数到x2IS0xffffffff对应于-1。由于-1是在范围[-2048,2047] ,该常数可以被加载有单个指令:addi x2, zero, -1。您还可以使用li伪指令:li, x2, -1汇编程序将其转换为addi x2, zero, -1.
lui+addi序列加载 32 位常量通常,我们需要一个lui+addi序列——两条指令——将 32 位常量加载到寄存器中。该lui指令编码 20 位立即数,而该addi指令编码 12 位立即数。lui和addi可以用来分别加载32位常数的高20位和低12位,。
让N是一个我们想要加载到寄存器中的 32 位常量:N ? n 31 ... n 0。然后,我们可以将这个常数分成高 20 位和低 12 位,分别为N U和N L:N U ? n 31 ... n 12 ; ñ大号?ñ 11 ... N 0
原则上,我们编码ñ ü在眼前的lui和ñ大号在眼前的addi。然而,如果 12 位立即数的最高有效位addi为1,则处理起来很困难,因为addi指令中编码的立即数被符号扩展为 32 位。如果是这种情况,则addi指令将不是N L而是将N L - 4096添加到目标寄存器中- -4096(或 -2 12)是当高 20 位为1 且低 12 位为0时的结果数。
为了补偿不需要的项-4096,我们可以将1添加到lui的立即数 - 立即数的 LSBlui对应于位#12 - 因此,向该立即数添加1会导致将4096添加到目标寄存器,从而抵消- 4096术语。
addi条指令加载 32 位常量上面解释的问题是由于直接输入所addi经历的符号扩展。符号扩展addi的立即数的决定可能是允许使用单个指令加载小整数-介于-2048和2047之间的整数,两者都包括在内addi。例如,如果立即数addi是零扩展而不是符号扩展,则不可能仅用一条指令将像-1这样的频繁常量加载到寄存器中。
li 在任何情况下,您始终可以使用li伪指令加载 32 位常量,而不必关心要加载的常量的值是什么。该伪指令可以将任何 32 位数字加载到寄存器中,因此与手动写入lui+addi序列相比,它更易于使用且不易出错。
如果数字适合addi的立即数字段 ( [-2048, 2047] ),汇编器会将li伪addi指令li翻译成一条指令,否则,将翻译成lui+addi序列,并且上面解释的复杂情况由汇编器自动处理。
我本来要说“使用ORI而不是ADDI”,但随后我阅读了《指令集手册》,结果证明这也不起作用,因为所有低12位立即数操作数都进行了符号扩展,即使对于逻辑运算也是如此。
在AFAICT中,您必须以预期使用设置低12位的指令的效果的方式来偏移输入高20位的值。因此,如果您希望最后20位的值是X,并且要用来ADDI设置低12位,而这些低12位在最左侧位置为1,则必须执行LUI (X+1)而不是LUI X。同样,如果您要用来XORI设置低12位,而这些低12位在最左侧位置为1,则必须这样做LUI (~X)(即X的按位倒数)而不是LUI X。
但是在您执行任何上述操作之前,我将先看一下您的汇编器是否已经具有某种“立即加载”伪操作或宏,可以为您解决此问题。如果没有,那么看看是否可以写一个:-)
RISC处理器需要程序员(或更常见的是编译器)进行这种额外的工作并不少见。这个想法是“使硬件保持简单,使其可以快速运行,并且这是否会使构建软件更困难也没有关系”。