RISC-V使用LUI和ADDI构建32位常量

Li *_*uan 5 riscv

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

这使x20xffffefff,但不0xffffffff

什么是立即移动32位进行注册的良好实现?

Pav*_*nov 7

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, 0xFFFFFFFFaddi x2,x0,-1


眠りネ*_*ネロク 7

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 位立即数。luiaddi可以用来分别加载32位常数的高20位和低12位,。

N是一个我们想要加载到寄存器中的 32 位常量:N ? n 31 ... n 0。然后,我们可以将这个常数分成高 20 位和低 12 位,分别为N UN LN U ? n 31 ... n 12 ; ñ大号?ñ 11 ... N 0

原则上,我们编码ñ ü在眼前的luiñ大号在眼前的addi。然而,如果 12 位立即数的最高有效位addi1,则处理起来很困难,因为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的立即数的决定可能是允许使用单个指令加载小整数-介于-20482047之间的整数,两者都包括在内addi。例如,如果立即数addi零扩展而不是符号扩展,则不可能仅用一条指令将像-1这样的频繁常量加载到寄存器中。


使用指令加载 32 位常量li

在任何情况下,您始终可以使用li伪指令加载 32 位常量,而不必关心要加载的常量的值是什么。该伪指令可以将任何 32 位数字加载到寄存器中,因此与手动写入lui+addi序列相比,它更易于使用且不易出错。

如果数字适合addi的立即数字段 ( [-2048, 2047] ),汇编器会将liaddi指令li翻译成一条指令,否则,将翻译成lui+addi序列,并且上面解释的复杂情况由汇编器自动处理。


ott*_*ter 5

我本来要说“使用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处理器需要程序员(或更常见的是编译器)进行这种额外的工作并不少见。这个想法是“使硬件保持简单,使其可以快速运行,并且这是否会使构建软件更困难也没有关系”。