]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elfnn-riscv.c
RISC-V: Fix lui relaxation issue with code at address 0.
[thirdparty/binutils-gdb.git] / bfd / elfnn-riscv.c
index 706dcb923f113bb9553ad7877afc09c1015c908a..d14c29e83315456356ebc83dc3a7f87749e9840a 100644 (file)
@@ -1482,9 +1482,21 @@ perform_relocation (const reloc_howto_type *howto,
       break;
 
     case R_RISCV_RVC_LUI:
-      if (!VALID_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (value)))
+      if (RISCV_CONST_HIGH_PART (value) == 0)
+       {
+         /* Linker relaxation can convert an address equal to or greater than
+            0x800 to slightly below 0x800.  C.LUI does not accept zero as a
+            valid immediate.  We can fix this by converting it to a C.LI.  */
+         bfd_vma insn = bfd_get (howto->bitsize, input_bfd,
+                                 contents + rel->r_offset);
+         insn = (insn & ~MATCH_C_LUI) | MATCH_C_LI;
+         bfd_put (howto->bitsize, input_bfd, insn, contents + rel->r_offset);
+         value = ENCODE_RVC_IMM (0);
+       }
+      else if (!VALID_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (value)))
        return bfd_reloc_overflow;
-      value = ENCODE_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (value));
+      else
+       value = ENCODE_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (value));
       break;
 
     case R_RISCV_32: