lightning
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] riscv: Fix movi/relatives loading incorrect value


From: Kim Kuparinen
Subject: [PATCH] riscv: Fix movi/relatives loading incorrect value
Date: Tue, 16 Nov 2021 17:04:45 +0200

Currently when loading the low 32 bits of a 64-bit constant LUI sign-extends
the value, leading to situations where the high 32 bits of the register are
effectively subtracted by one.

Simplified example, using 8-bit registers: lui loads the upper two bits and
sign-extends them, addiw adds the bottom two bits and ignores overflow.

movi a0, 0b0010 1001

is expanded to
// lo
lui r0, 0b10    // r0 => 0b1111 1000
addiw r0, 0b01  // r0 => 0b1111 1001
// hi
lui a0, 0b00    // a0 => 0b0000 0000
addiw a0, b10   // a0 => 0b0000 0010
slli a0, 4      // a0 => 0b0010 0000
add a0, a0, r0  // a0 => 0b0001 1001

The fix I came up with is to detect if lo is negative and add one to hi,
cancelling out the effective -1.

---
 lib/jit_riscv-cpu.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/lib/jit_riscv-cpu.c b/lib/jit_riscv-cpu.c
index 388489f..7e21d24 100644
--- a/lib/jit_riscv-cpu.c
+++ b/lib/jit_riscv-cpu.c
@@ -1342,6 +1342,10 @@ _movi(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
        jit_int32_t     lo = i0 << 32 >> 32;
        jit_word_t      hi = i0 - lo;
        jit_int32_t     t0 = jit_get_reg(jit_class_gpr);
+
+       if(lo < 0)
+               hi++;
+
        movi(rn(t0), (jit_int32_t)(hi >> 32));
        movi(r0, lo);
        lshi(rn(t0), rn(t0), 32);
@@ -1363,6 +1367,10 @@ _movi_p(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
     LUI(r0, hi >> 12);
     ADDIW(r0, r0, lo);
     ww = i0 >> 32;
+
+    if(hi < 0)
+           ww++;
+
     lo = ww << 20 >> 20;
     hi = ww - lo;
     LUI(rn(t0), hi >> 12);
@@ -2331,6 +2339,10 @@ _patch_at(jit_state_t *_jit, jit_word_t instr, 
jit_word_t label)
            i.w = u.i[2];
            if (i.U.opcode == 55) {                             /* LUI */
                ww = label >> 32;
+
+               if(hi < 0)
+                       ww++;
+
                lo = ww << 20 >> 20;
                hi = ww - lo;
                i.U.imm12_31 = hi >> 12;
-- 
2.33.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]