[PATCH] RISC-V: Fix the asm code for large code model

Kito Cheng kito.cheng@sifive.com
Tue Apr 1 14:04:21 GMT 2025


The large code model assume the data may far away from the code, so we
must put the address of the target data wihin the `.text` section,
normally we will just put within the function or nearby the function to
prevent it out-of-range.

Report from riscv-gnu-toolchain:
https://github.com/riscv-collab/riscv-gnu-toolchain/issues/1699

Verified with riscv-gnu-toolchain with rv64gc.
---
 libgloss/riscv/crt0.S              | 39 ++++++++++++++++++++++++++++++
 newlib/libc/machine/riscv/strcmp.S |  9 ++++++-
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/libgloss/riscv/crt0.S b/libgloss/riscv/crt0.S
index 54443e412..aa5ac3684 100644
--- a/libgloss/riscv/crt0.S
+++ b/libgloss/riscv/crt0.S
@@ -27,8 +27,13 @@ _start:
 .option pop
 
   /* Initialize jvt CSR (reg addr: 0x0017) */
+#ifndef __riscv_cmodel_large
   .weak __jvt_base$
   lla a0, __jvt_base$
+#else
+  la a0, .Laddr_jvt_base
+  ld a0, 0(a0)
+#endif
   beqz a0, .Ljvt_init_end
 .option push
 .option norelax
@@ -38,21 +43,38 @@ _start:
 .Ljvt_init_end:
 
   # Clear the bss segment
+#ifndef __riscv_cmodel_large
   la      a0, __bss_start
   la      a2, _end
+#else
+  la      a0, .Laddr_bss_start
+  ld      a0, 0(a0)
+  la      a2, .Laddr_end
+  ld      a2, 0(a2)
+#endif
   sub     a2, a2, a0
   li      a1, 0
   call    memset
 #ifdef _LITE_EXIT
   # Make reference to atexit weak to avoid unconditionally pulling in
   # support code.  Refer to comments in __atexit.c for more details.
+#ifndef __riscv_cmodel_large
   .weak   atexit
   la      a0, atexit
+#else
+  la      a0, .Laddr_atexit
+  ld      a0, 0(a0)
+#endif
   beqz    a0, .Lweak_atexit
   .weak   __libc_fini_array
 #endif
 
+#ifndef __riscv_cmodel_large
   la      a0, __libc_fini_array   # Register global termination functions
+#else
+  la      a0, .Laddr_libc_fini_array
+  ld      a0, 0(a0)
+#endif
   call    atexit                  #  to be called upon exit
 #ifdef _LITE_EXIT
 .Lweak_atexit:
@@ -66,4 +88,21 @@ _start:
   add     a2, a2, a1                 # a2 = envp
   call    main
   tail    exit
+#ifdef __riscv_cmodel_large
+.Laddr_gp:
+  .dword __global_pointer$
+.Laddr_jvt_base:
+  .weak __jvt_base$
+  .dword __jvt_base$
+.Laddr_bss_start:
+  .dword __bss_start
+.Laddr_end:
+  .dword _end
+.Laddr_atexit:
+  .weak   atexit
+  .dword atexit
+.Laddr_libc_fini_array:
+  .weak   __libc_fini_array
+  .dword __libc_fini_array
+#endif
   .size  _start, .-_start
diff --git a/newlib/libc/machine/riscv/strcmp.S b/newlib/libc/machine/riscv/strcmp.S
index 12c39db94..cc29b7b8b 100644
--- a/newlib/libc/machine/riscv/strcmp.S
+++ b/newlib/libc/machine/riscv/strcmp.S
@@ -188,9 +188,16 @@ strcmp:
   foundnull 1 3
   foundnull 2 3
 #endif
+#ifdef __riscv_cmodel_large
+  # Put the data within the funciton for large code model to prevent
+  # the data put too far.
+.align 3
+mask:
+.dword 0x7f7f7f7f7f7f7f7f
+#endif
 .size	strcmp, .-strcmp
 
-#if SZREG == 8
+#if SZREG == 8 && !defined(__riscv_cmodel_large)
 .section .srodata.cst8,"aM",@progbits,8
 .align 3
 mask:
-- 
2.34.1



More information about the Newlib mailing list