简体   繁体   English

RISC-V使用LUI / ADDI在寄存器中生成-1 / 0xFFFFFFFF吗?

[英]RISC-V generate -1 / 0xFFFFFFFF in a register with LUI / ADDI?

I am learning how to write code for a RISC-V processor. 我正在学习如何为RISC-V处理器编写代码。 I want to store a value of 0xFFFFFFFF into memory / a register. 我想将0xFFFFFFFF的值存储到内存/寄存器中。

I can extend the 12 immediate bits of addi instruction by adding a lui before it, something like this: 我可以通过在其前面添加一个lui来扩展addi指令的12个立即数,如下所示:

lui t0, 0xFFFFF
addi t0, t0, 0x7FF

But the result will end up something like 0xFFFFF7FF . 但是结果最终将类似于0xFFFFF7FF

So then, how can I generate that value? 那么,我该如何产生该价值呢?

Ask a C compiler: 询问C编译器:

unsigned foo(){return 0xFFFFFFFF;}

compiles to this asm with Clang -O3 for RISC-V (on Godbolt) : 使用Clang -O3针对RISC-V编译到此asm (在Godbolt上)

foo():
    addi    a0, zero, -1
    ret

(gcc just uses the li a0, -1 pseudo-instruction and leaves the details to the assembler. Normally you should do the same, unless you want to think about choosing constants that can be generated more efficiently.) (gcc仅使用li a0, -1伪指令并将细节留给汇编器。通常,您应该执行相同的操作,除非您想考虑选择可以更高效地生成的常量。)


RISC-V addi sign-extends its immediate operand to 32 (or 64) bits , so if you want a one in the 12th bit, you need to account for that in your choice for the upper bits. RISC-V addi将其立即数符号扩展为32(或64)位 ,因此,如果要在第12位中添加一个,则需要在选择高位时加以考虑。

In this case, the right starting value for the upper bits is 0 so you can optimize away the lui entirely. 在这种情况下,高位的正确起始值为0因此您可以完全优化lui

RISC-V uses 2's complement signed integers so sign-extension just means duplicating the sign bit to all higher positions when widening. RISC-V使用2的补码有符号整数,因此符号扩展仅表示加宽时将符号位复制到所有较高位置。

Let's first analyse where the problem with your code is: 首先让我们分析代码的问题所在:

lui t0, 0xFFFFF
addi t0, t0, 0x7FF
  • The lui instruction loads into t0 the value resulting from left shifting the 20-bit immediate 0xFFFFF by 12 bits. lui指令将20位立即数0xFFFFF左移12位后得到的值加载到t0 Therefore, t0 results in 0xFFFFF000 . 因此, t0导致0xFFFFF000
  • The addi sign extends the 12-bit immediate 0x7FF , and adds it to the register t0 . addi 号扩展了12位立即数0x7FF ,并将其添加到寄存器t0 Since the most significant bit (ie, the sign bit) of the immediate is zero, its sign extended 32-bit value is 0x000007FF . 由于立即数的最高有效位(即符号位)为零,因此其符号扩展的32位值为0x000007FF This value is then added to t0 , which was previously 0xFFFFF000 . 然后将此值添加到t0 ,之前为0xFFFFF000 Therefore, the resulting value of t0 is 0xFFFFF7FF . 因此, t0的结果值为0xFFFFF7FF

As already explained in this answer , you can optimise away the lui instruction by taking advantage of how the sign extension works: sign extension propagates the sign bit, which is the most significant bit. 该答案中已经解释的,您可以通过利用符号扩展的工作方式来优化lui指令:符号扩展会传播符号位,这是最高有效位。

The 12-bit immediate 0xFFF consists of all 1 s, including the most significant bit (ie, the sign bit). 12位立即数0xFFF1组成,包括最高有效位(即符号位)。 Therefore, its 32-bit sign extension is 0xFFFFFFFF , which already corresponds to the value you want: 因此,其32位符号扩展名是0xFFFFFFFF ,它已经对应于您想要的值:

addi t0, zero, 0xFFF

If you keep insisting on using both instructions, lui and addi , simply load all 0 s into the upper bits of t0 : 如果您一直坚持使用luiaddi这两个指令,只需将所有0加载到t0的高位:

lui t0, 0
addi t0, t0, 0xFFF

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM