RISC-V build 32-bit constants with LUI and ADDI

Li Hanyuan picture Li Hanyuan · Jun 7, 2018 · Viewed 10.9k times · Source

LUI (load upper immediate) is used to build 32-bit constants and uses the U-type format. LUI places the U-immediate value in the top 20 bits of the destination register rd, filling in the lowest 12 bits with zeros.

I found this in manual, but if I want to move 0xffffffff to a register, all the code I need is:

LUI x2, 0xfffff000
ADDI x2, x2, 0xfff

But a problem occurred, ADDI will extend sign to make a immediate data to a signed number, so 0xfff will be extend to 0xffffffff.

It make x2 to 0xffffefff but not 0xffffffff

and what is an good implementation to move a 32bits immediate to register?

Answer

Pavel Smirnov picture Pavel Smirnov · Jun 9, 2018

The RISC-V assembler supports the pseudo-instruction li x2, 0xFFFFFFFF.

Let Nis a signed, 2's complement 32 bit integer.

Common case implementation of li x2,N is:

    # 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

Of course, to load short immediate li can use

   addi x2,x0,imm

So, li x2, 0xFFFFFFFF is addi x2,x0,-1.