[v6,4/6] LoongArch: Add support for LA32 in sysdeps/unix/sysv/linux/loongarch

Message ID 20260312014203.1916933-5-mengqinggang@loongson.cn (mailing list archive)
State Under Review
Delegated to: Adhemerval Zanella Netto
Headers
Series Add support for LoongArch32 |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Test passed

Commit Message

mengqinggang March 12, 2026, 1:42 a.m. UTC
  ---
 sysdeps/unix/sysv/linux/loongarch/Makefile    |  4 +-
 sysdeps/unix/sysv/linux/loongarch/clone.S     | 10 ++---
 sysdeps/unix/sysv/linux/loongarch/clone3.S    |  8 ++--
 sysdeps/unix/sysv/linux/loongarch/configure   | 44 +++++++++++++++++++
 .../unix/sysv/linux/loongarch/configure.ac    | 12 +++++
 .../unix/sysv/linux/loongarch/getcontext.S    | 12 ++---
 .../unix/sysv/linux/loongarch/gettimeofday.c  |  9 ++--
 .../unix/sysv/linux/loongarch/ldd-rewrite.sed |  2 +-
 .../linux/loongarch/{ => lp64}/arch-syscall.h |  0
 .../unix/sysv/linux/loongarch/pointer_guard.h | 18 ++------
 .../unix/sysv/linux/loongarch/readelflib.c    | 33 +++++++++++---
 .../unix/sysv/linux/loongarch/setcontext.S    | 24 +++++-----
 .../unix/sysv/linux/loongarch/shlib-versions  | 10 ++++-
 .../unix/sysv/linux/loongarch/swapcontext.S   | 28 ++++++------
 .../sysv/linux/loongarch/syscall_cancel.S     |  2 +-
 sysdeps/unix/sysv/linux/loongarch/sysdep.S    |  8 ++--
 sysdeps/unix/sysv/linux/loongarch/sysdep.h    | 30 ++++++++++---
 .../sysv/linux/loongarch/ucontext-macros.h    |  6 ++-
 sysdeps/unix/sysv/linux/loongarch/vfork.S     |  6 +--
 19 files changed, 181 insertions(+), 85 deletions(-)
 rename sysdeps/unix/sysv/linux/loongarch/{ => lp64}/arch-syscall.h (100%)
  

Patch

diff --git a/sysdeps/unix/sysv/linux/loongarch/Makefile b/sysdeps/unix/sysv/linux/loongarch/Makefile
index c84a1762ed..0d5f087862 100644
--- a/sysdeps/unix/sysv/linux/loongarch/Makefile
+++ b/sysdeps/unix/sysv/linux/loongarch/Makefile
@@ -2,11 +2,13 @@  ifeq ($(subdir),stdlib)
 gen-as-const-headers += ucontext_i.sym
 endif
 
-abi-variants := lp64s lp64d
+abi-variants := ilp32s ilp32d lp64s lp64d
 
 ifeq (,$(filter $(default-abi),$(abi-variants)))
 $(error Unknown ABI $(default-abi), must be one of $(abi-variants))
 endif
 
+abi-ilp32s-condition	:= __WORDSIZE == 32 && defined __loongarch_soft_float
+abi-ilp32d-condition	:= __WORDSIZE == 32 && defined __loongarch_double_float
 abi-lp64s-condition	:= __WORDSIZE == 64 && defined __loongarch_soft_float
 abi-lp64d-condition	:= __WORDSIZE == 64 && defined __loongarch_double_float
diff --git a/sysdeps/unix/sysv/linux/loongarch/clone.S b/sysdeps/unix/sysv/linux/loongarch/clone.S
index fcf8316a43..e815df6a24 100644
--- a/sysdeps/unix/sysv/linux/loongarch/clone.S
+++ b/sysdeps/unix/sysv/linux/loongarch/clone.S
@@ -33,13 +33,13 @@ 
 ENTRY (__clone)
 
 	/* Align stack to 16.  */
-	BSTRINS		a1, zero, 3, 0
+	REG_ALIGN_ASM (a1, 4)
 
 	/* Sanity check arguments.  */
-	beqz		a0, L (invalid) /* No NULL function pointers.  */
-	beqz		a1, L (invalid) /* No NULL stack pointers.  */
+	beq		a0, zero, L (invalid) /* No NULL function pointers.  */
+	beq		a1, zero, L (invalid) /* No NULL stack pointers.  */
 
-	ADDI 		a1, a1, -16 /* Reserve argument save space.  */
+	ADDI 		a1, a1, -STACK_ALIGN /* Reserve argument save space.  */
 	REG_S		a0, a1, 0   /* Save function pointer.  */
 	REG_S		a3, a1, SZREG   /* Save argument pointer.  */
 
@@ -54,7 +54,7 @@  ENTRY (__clone)
 	syscall		0
 
 	blt		a0, zero ,L (error)
-	beqz		a0,L (thread_start)
+	beq		a0, zero, L (thread_start)
 
 	/* Successful return from the parent.  */
 	ret
diff --git a/sysdeps/unix/sysv/linux/loongarch/clone3.S b/sysdeps/unix/sysv/linux/loongarch/clone3.S
index cfd5e3b817..a8f71487fa 100644
--- a/sysdeps/unix/sysv/linux/loongarch/clone3.S
+++ b/sysdeps/unix/sysv/linux/loongarch/clone3.S
@@ -33,15 +33,15 @@ 
 ENTRY (__clone3)
 
 	/* Sanity check arguments.  */
-	beqz		a0, L (invalid)	/* No NULL cl_args pointer.  */
-	beqz		a2, L (invalid)	/* No NULL function pointer.  */
+	beq		a0, zero, L (invalid)	/* No NULL cl_args pointer.  */
+	beq		a2, zero, L (invalid)	/* No NULL function pointer.  */
 
 	/* Do the system call.  */
 	LI		a7, __NR_clone3
 	syscall		0
 
 	blt		a0, zero ,L (error)
-	beqz		a0, L (thread_start3)
+	beq		a0, zero, L (thread_start3)
 
 	/* Successful return from the parent.  */
 	ret
@@ -67,7 +67,7 @@  L (thread_start3):
 	cfi_undefined (1)
 
 	/* Align stack to 16.  */
-	BSTRINS		sp, zero, 3, 0
+	REG_ALIGN_ASM (sp, 4)
 
 	/* Set up arguments for the function call.  */
 	move		a0, a3		/* Argument.  */
diff --git a/sysdeps/unix/sysv/linux/loongarch/configure b/sysdeps/unix/sysv/linux/loongarch/configure
index 914943f914..8ac792f6cf 100644
--- a/sysdeps/unix/sysv/linux/loongarch/configure
+++ b/sysdeps/unix/sysv/linux/loongarch/configure
@@ -152,10 +152,26 @@  then :
 fi
 rm -rf conftest*
 
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+__SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_POINTER__
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP_TRADITIONAL "4 4 4" >/dev/null 2>&1
+then :
+  libc_cv_loongarch_int_abi=ilp32
+fi
+rm -rf conftest*
+
 if test $libc_cv_loongarch_int_abi = no; then
   as_fn_error $? "Unable to determine integer ABI" "$LINENO" 5
 fi
 
+if test $libc_cv_loongarch_int_abi = ilp32; then
+  arch_minimum_kernel=6.19.0
+fi
+
 libc_cv_loongarch_float_abi=no
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
@@ -193,6 +209,34 @@  config_vars="$config_vars
 default-abi = $libc_cv_loongarch_int_abi$libc_cv_loongarch_float_abi"
 
 case $libc_cv_loongarch_int_abi$libc_cv_loongarch_float_abi in
+ilp32s)
+  test -n "$libc_cv_slibdir" ||
+case "$prefix" in
+/usr | /usr/)
+  libc_cv_slibdir='/lib32/sf'
+  libc_cv_rtlddir='/lib32'
+  if test "$libdir" = '${exec_prefix}/lib'; then
+    libdir='${exec_prefix}/lib32/sf';
+    # Locale data can be shared between 32-bit and 64-bit libraries.
+    libc_cv_complocaledir='${exec_prefix}/lib/locale'
+  fi
+  ;;
+esac
+  ;;
+ilp32d)
+  test -n "$libc_cv_slibdir" ||
+case "$prefix" in
+/usr | /usr/)
+  libc_cv_slibdir='/lib32'
+  libc_cv_rtlddir='/lib32'
+  if test "$libdir" = '${exec_prefix}/lib'; then
+    libdir='${exec_prefix}/lib32';
+    # Locale data can be shared between 32-bit and 64-bit libraries.
+    libc_cv_complocaledir='${exec_prefix}/lib/locale'
+  fi
+  ;;
+esac
+  ;;
 lp64s)
   test -n "$libc_cv_slibdir" ||
 case "$prefix" in
diff --git a/sysdeps/unix/sysv/linux/loongarch/configure.ac b/sysdeps/unix/sysv/linux/loongarch/configure.ac
index 04e9150a9b..35d5acfbb8 100644
--- a/sysdeps/unix/sysv/linux/loongarch/configure.ac
+++ b/sysdeps/unix/sysv/linux/loongarch/configure.ac
@@ -7,10 +7,16 @@  arch_minimum_kernel=5.19.0
 libc_cv_loongarch_int_abi=no
 AC_EGREP_CPP(4 8 8, [__SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_POINTER__
   ], libc_cv_loongarch_int_abi=lp64)
+AC_EGREP_CPP(4 4 4, [__SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_POINTER__
+  ], libc_cv_loongarch_int_abi=ilp32)
 if test $libc_cv_loongarch_int_abi = no; then
   AC_MSG_ERROR([Unable to determine integer ABI])
 fi
 
+if test $libc_cv_loongarch_int_abi = ilp32; then
+  arch_minimum_kernel=6.19.0
+fi
+
 libc_cv_loongarch_float_abi=no
 AC_EGREP_CPP(yes, [#ifdef __loongarch_double_float
 		   yes
@@ -27,6 +33,12 @@  fi
 LIBC_CONFIG_VAR([default-abi], [$libc_cv_loongarch_int_abi$libc_cv_loongarch_float_abi])
 
 case $libc_cv_loongarch_int_abi$libc_cv_loongarch_float_abi in
+ilp32s)
+  LIBC_SLIBDIR_RTLDDIR([lib32/sf], [lib32])
+  ;;
+ilp32d)
+  LIBC_SLIBDIR_RTLDDIR([lib32], [lib32])
+  ;;
 lp64s)
   LIBC_SLIBDIR_RTLDDIR([lib64/sf], [lib64])
   ;;
diff --git a/sysdeps/unix/sysv/linux/loongarch/getcontext.S b/sysdeps/unix/sysv/linux/loongarch/getcontext.S
index f012e059d7..120738b7c9 100644
--- a/sysdeps/unix/sysv/linux/loongarch/getcontext.S
+++ b/sysdeps/unix/sysv/linux/loongarch/getcontext.S
@@ -36,16 +36,16 @@  LEAF (__getcontext)
 	SAVE_INT_REG (s6,  29, a0)
 	SAVE_INT_REG (s7,  30, a0)
 	SAVE_INT_REG (s8,  31, a0)
-	st.d		ra, a0, MCONTEXT_PC
+	REG_S		ra, a0, MCONTEXT_PC
 
 /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
-	li.d		a3, _NSIG8
-	li.d		a2, UCONTEXT_SIGMASK
-	add.d		a2, a2, a0
+	LI		a3, _NSIG8
+	LI		a2, UCONTEXT_SIGMASK
+	ADD		a2, a2, a0
 	ori		a1, zero,0
-	li.d		a0, SIG_BLOCK
+	LI		a0, SIG_BLOCK
 
-	li.d		a7, SYS_ify (rt_sigprocmask)
+	LI		a7, SYS_ify (rt_sigprocmask)
 	syscall		0
 	blt		a0, zero, 99f
 
diff --git a/sysdeps/unix/sysv/linux/loongarch/gettimeofday.c b/sysdeps/unix/sysv/linux/loongarch/gettimeofday.c
index 514142d340..adb80fc975 100644
--- a/sysdeps/unix/sysv/linux/loongarch/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/loongarch/gettimeofday.c
@@ -17,6 +17,9 @@ 
    License along with the GNU C Library.  If not, see
    <https://www.gnu.org/licenses/>.  */
 
-
-#define USE_IFUNC_GETTIMEOFDAY
-#include <sysdeps/unix/sysv/linux/gettimeofday.c>
+#ifdef __loongarch64
+# define USE_IFUNC_GETTIMEOFDAY
+# include <sysdeps/unix/sysv/linux/gettimeofday.c>
+#else
+# include <sysdeps/unix/sysv/linux/gettimeofday.c>
+#endif
diff --git a/sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed b/sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed
index cdbe5c3dc5..a868370aca 100644
--- a/sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed
+++ b/sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed
@@ -1 +1 @@ 
-s_^\(RTLDLIST=\)\(.*lib\)\(\|64\|32\)\(/ld-linux-loongarch-\)\(lp\|ilp\)\(64\|32\)\(d\|s\)\(\.so\.[0-9.]*\)[[:blank:]]*$_\1"\264\4lp64d\8 \264\4lp64s\8"_
+s_^\(RTLDLIST=\)\(.*lib\)\(\|64\|32\)\(/ld-linux-loongarch-\)\(lp\|ilp\)\(64\|32\)\(d\|s\)\(\.so\.[0-9.]*\)[[:blank:]]*$_\1"\264\4lp64d\8 \264\4lp64s\8 \232\4ilp32d\8 \232\4ilp32s\8"_
diff --git a/sysdeps/unix/sysv/linux/loongarch/arch-syscall.h b/sysdeps/unix/sysv/linux/loongarch/lp64/arch-syscall.h
similarity index 100%
rename from sysdeps/unix/sysv/linux/loongarch/arch-syscall.h
rename to sysdeps/unix/sysv/linux/loongarch/lp64/arch-syscall.h
diff --git a/sysdeps/unix/sysv/linux/loongarch/pointer_guard.h b/sysdeps/unix/sysv/linux/loongarch/pointer_guard.h
index a28da43c81..69150c0211 100644
--- a/sysdeps/unix/sysv/linux/loongarch/pointer_guard.h
+++ b/sysdeps/unix/sysv/linux/loongarch/pointer_guard.h
@@ -19,26 +19,16 @@ 
 #ifndef POINTER_GUARD_H
 #define POINTER_GUARD_H
 
-/* Load a got-relative EXPR into register G.  */
-#define LD_GLOBAL(G, EXPR) \
-  la.global G,  EXPR; \
-  REG_L     G,  G,  0;
-
-/* Load a pc-relative EXPR into register G.  */
-#define LD_PCREL(G, EXPR) \
-  pcalau12i G, %pc_hi20(EXPR); \
-  REG_L     G, G, %pc_lo12(EXPR);
-
 #if (IS_IN (rtld) \
      || (!defined SHARED && (IS_IN (libc) \
      || IS_IN (libpthread))))
 
 #ifdef __ASSEMBLER__
 #define PTR_MANGLE(dst, src, guard) \
-  LD_PCREL (guard, __pointer_chk_guard_local); \
+  LOAD_LOCAL (guard, __pointer_chk_guard_local); \
   PTR_MANGLE2 (dst, src, guard);
 #define PTR_DEMANGLE(dst, src, guard) \
-  LD_PCREL (guard, __pointer_chk_guard_local); \
+  LOAD_LOCAL (guard, __pointer_chk_guard_local); \
   PTR_DEMANGLE2 (dst, src, guard);
 /* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */
 #define PTR_MANGLE2(dst, src, guard) \
@@ -57,10 +47,10 @@  extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
 
 #ifdef __ASSEMBLER__
 #define PTR_MANGLE(dst, src, guard) \
-  LD_GLOBAL (guard, __pointer_chk_guard); \
+  LOAD_GLOBAL (guard, __pointer_chk_guard); \
   PTR_MANGLE2 (dst, src, guard);
 #define PTR_DEMANGLE(dst, src, guard) \
-  LD_GLOBAL (guard, __pointer_chk_guard); \
+  LOAD_GLOBAL (guard, __pointer_chk_guard); \
   PTR_DEMANGLE2 (dst, src, guard);
 /* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */
 #define PTR_MANGLE2(dst, src, guard) \
diff --git a/sysdeps/unix/sysv/linux/loongarch/readelflib.c b/sysdeps/unix/sysv/linux/loongarch/readelflib.c
index 8045ba2bc1..7186f6859d 100644
--- a/sysdeps/unix/sysv/linux/loongarch/readelflib.c
+++ b/sysdeps/unix/sysv/linux/loongarch/readelflib.c
@@ -17,6 +17,9 @@ 
    <https://www.gnu.org/licenses/>.  */
 
 
+int process_elf32_file (const char *file_name, const char *lib,
+			int *flag, unsigned int *isa_level, char **soname,
+			void *file_contents, size_t file_length);
 int process_elf64_file (const char *file_name, const char *lib,
 			int *flag, unsigned int *isa_level, char **soname,
 			void *file_contents, size_t file_length);
@@ -31,6 +34,7 @@  process_elf_file (const char *file_name, const char *lib, int *flag,
 		  size_t file_length)
 {
   ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_contents;
+  Elf32_Ehdr *elf32_header = (Elf32_Ehdr *) elf_header;
   Elf64_Ehdr *elf64_header = (Elf64_Ehdr *) elf_header;
   int ret;
   long flags;
@@ -38,15 +42,24 @@  process_elf_file (const char *file_name, const char *lib, int *flag,
   /* LoongArch libraries are always libc.so.6+.  */
   *flag = FLAG_ELF_LIBC6;
 
-  ret = process_elf64_file (file_name, lib, flag, isa_level, soname,
+  if (elf_header->e_ident[EI_CLASS] == ELFCLASS32)
+    {
+      ret = process_elf32_file (file_name, lib, flag, isa_level, soname,
+				file_contents, file_length);
+      flags = elf32_header->e_flags & ~EF_LARCH_OBJABI_V1;
+    }
+  else
+    {
+      ret = process_elf64_file (file_name, lib, flag, isa_level, soname,
 				file_contents, file_length);
 
-  /* The EF_LARCH_OBJABI_V1 flag indicate which set of static relocations
-   the object might use and it only considered during static linking,
-   it does not reflect in runtime relocations.  However some binutils
-   version might set it on dynamic shared object, so clear it to avoid
-   see the SO as unsupported.  */
-  flags = elf64_header->e_flags & ~EF_LARCH_OBJABI_V1;
+      /* The EF_LARCH_OBJABI_V1 flag indicate which set of static relocations
+       the object might use and it only considered during static linking,
+       it does not reflect in runtime relocations.  However some binutils
+       version might set it on dynamic shared object, so clear it to avoid
+       see the SO as unsupported.  */
+      flags = elf64_header->e_flags & ~EF_LARCH_OBJABI_V1;
+    }
 
   /* LoongArch linkers encode the floating point ABI as part of the ELF headers.  */
   switch (flags & SUPPORTED_ELF_FLAGS)
@@ -70,6 +83,12 @@  process_elf_file (const char *file_name, const char *lib, int *flag,
 }
 
 #undef __ELF_NATIVE_CLASS
+#undef process_elf_file
+#define process_elf_file process_elf32_file
+#define __ELF_NATIVE_CLASS 32
+#include "elf/readelflib.c"
+#undef __ELF_NATIVE_CLASS
+
 #undef process_elf_file
 #define process_elf_file process_elf64_file
 #define __ELF_NATIVE_CLASS 64
diff --git a/sysdeps/unix/sysv/linux/loongarch/setcontext.S b/sysdeps/unix/sysv/linux/loongarch/setcontext.S
index e7189c0c41..269aca8026 100644
--- a/sysdeps/unix/sysv/linux/loongarch/setcontext.S
+++ b/sysdeps/unix/sysv/linux/loongarch/setcontext.S
@@ -30,22 +30,22 @@ 
 	.text
 LEAF (__setcontext)
 
-	addi.d		sp, sp, -16
-	st.d		a0, sp, 0	/* Save ucp to stack */
+	ADDI		sp, sp, -16
+	REG_S		a0, sp, 0	/* Save ucp to stack */
 
 /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8) */
-	li.d		a3, _NSIG8
-	li.d		a2, 0
-	li.d		a1, UCONTEXT_SIGMASK
-	add.d		a1, a1, a0
-	li.d		a0, SIG_SETMASK
+	LI		a3, _NSIG8
+	LI		a2, 0
+	LI		a1, UCONTEXT_SIGMASK
+	ADD		a1, a1, a0
+	LI		a0, SIG_SETMASK
 
-	li.d		a7, SYS_ify (rt_sigprocmask)
+	LI		a7, SYS_ify (rt_sigprocmask)
 	syscall		0
 
 	blt		a0, $r0, 99f
 
-	ld.d		t0, sp, 0	/* Load ucp to t0 */
+	REG_L		t0, sp, 0	/* Load ucp to t0 */
 	cfi_def_cfa (12, 0)
 
 /* Note the contents of argument registers will be random
@@ -72,11 +72,11 @@  LEAF (__setcontext)
 	RESTORE_INT_REG(s7,  30, t0)
 	RESTORE_INT_REG(s8,  31, t0)
 
-	ld.d		t1, t0, MCONTEXT_PC
+	REG_L		t1, t0, MCONTEXT_PC
 	jirl		$r0,t1,0
 
 99:
-	addi.d		sp, sp, 16
+	ADDI		sp, sp, 16
 	b		__syscall_error
 
 PSEUDO_END (__setcontext)
@@ -92,7 +92,7 @@  LEAF (__start_context)
 
 	/* Invoke subsequent context if present, else exit(0).  */
 	ori		a0, s2, 0
-	beqz		s2, 1f
+	beq		s2, zero, 1f
 	bl		__setcontext
 1:
 	b		HIDDEN_JUMPTARGET(exit)
diff --git a/sysdeps/unix/sysv/linux/loongarch/shlib-versions b/sysdeps/unix/sysv/linux/loongarch/shlib-versions
index 5f40e7f5ec..7fb62abd4f 100644
--- a/sysdeps/unix/sysv/linux/loongarch/shlib-versions
+++ b/sysdeps/unix/sysv/linux/loongarch/shlib-versions
@@ -1,8 +1,14 @@ 
+%if LOONGARCH_ABI_GRLEN == 32 && LOONGARCH_ABI_FRLEN == 64
+DEFAULT		GLIBC_2.44
+ld=ld-linux-loongarch-ilp32d.so.1
+%elif LOONGARCH_ABI_GRLEN == 32 && LOONGARCH_ABI_FRLEN == 0
+DEFAULT		GLIBC_2.44
+ld=ld-linux-loongarch-ilp32s.so.1
+%elif LOONGARCH_ABI_GRLEN == 64 && LOONGARCH_ABI_FRLEN == 64
 DEFAULT		GLIBC_2.36
-
-%if LOONGARCH_ABI_GRLEN == 64 && LOONGARCH_ABI_FRLEN == 64
 ld=ld-linux-loongarch-lp64d.so.1
 %elif LOONGARCH_ABI_GRLEN == 64 && LOONGARCH_ABI_FRLEN == 0
+DEFAULT		GLIBC_2.36
 ld=ld-linux-loongarch-lp64s.so.1
 %else
 %error cannot determine ABI
diff --git a/sysdeps/unix/sysv/linux/loongarch/swapcontext.S b/sysdeps/unix/sysv/linux/loongarch/swapcontext.S
index 905fc33a2e..afa31e250b 100644
--- a/sysdeps/unix/sysv/linux/loongarch/swapcontext.S
+++ b/sysdeps/unix/sysv/linux/loongarch/swapcontext.S
@@ -22,8 +22,8 @@ 
 
 LEAF (__swapcontext)
 	ori		a2, sp, 0		/* Save sp to a2 */
-	addi.d		sp, sp, -16
-	st.d		a1, sp, 0
+	ADDI		sp, sp, -16
+	REG_S		a1, sp, 0
 	ori		t0, a1, 0
 
 	SAVE_INT_REG (ra,   1, a0)
@@ -41,22 +41,22 @@  LEAF (__swapcontext)
 	SAVE_INT_REG (s7,  30, a0)
 	SAVE_INT_REG (s8,  31, a0)
 
-	st.d		ra, a0, MCONTEXT_PC
+	REG_S		ra, a0, MCONTEXT_PC
 
 /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask, _NSIG8) */
-	li.d		a3, _NSIG8
-	li.d		a2, UCONTEXT_SIGMASK
-	add.d		a2, a2, a0
-	li.d		a1, UCONTEXT_SIGMASK
-	add.d		a1, a1, t0
-	li.d		a0, SIG_SETMASK
-
-	li.d		a7, SYS_ify (rt_sigprocmask)
+	LI		a3, _NSIG8
+	LI		a2, UCONTEXT_SIGMASK
+	ADD		a2, a2, a0
+	LI		a1, UCONTEXT_SIGMASK
+	ADD		a1, a1, t0
+	LI		a0, SIG_SETMASK
+
+	LI		a7, SYS_ify (rt_sigprocmask)
 	syscall		0
 
 	blt		a0, zero, 99f
 
-	ld.d		t0, sp, 0		/* Load a1 to t0 */
+	REG_L		t0, sp, 0		/* Load a1 to t0 */
 
 /* Note the contents of argument registers will be random
    unless makecontext() has been called.  */
@@ -82,12 +82,12 @@  LEAF (__swapcontext)
 	RESTORE_INT_REG (s7,  30, t0)
 	RESTORE_INT_REG (s8,  31, t0)
 
-	ld.d		t1, t0, MCONTEXT_PC
+	REG_L		t1, t0, MCONTEXT_PC
 	jirl		$r0, t1, 0
 
 
 99:
-	addi.d		sp, sp, 16
+	ADDI		sp, sp, 16
 	b		__syscall_error
 
 PSEUDO_END (__swapcontext)
diff --git a/sysdeps/unix/sysv/linux/loongarch/syscall_cancel.S b/sysdeps/unix/sysv/linux/loongarch/syscall_cancel.S
index 387e455f74..3559c6210e 100644
--- a/sysdeps/unix/sysv/linux/loongarch/syscall_cancel.S
+++ b/sysdeps/unix/sysv/linux/loongarch/syscall_cancel.S
@@ -28,7 +28,7 @@  __syscall_cancel_arch_start:
 	     __syscall_do_cancel()  */
 	ld.w	t0, a0, 0
 	andi	t0, t0, TCB_CANCELED_BITMASK
-	bnez	t0, 1f
+	bne	t0, zero, 1f
 
 	/* Issue a 6 argument syscall.  */
 	move	t1, a1
diff --git a/sysdeps/unix/sysv/linux/loongarch/sysdep.S b/sysdeps/unix/sysv/linux/loongarch/sysdep.S
index e2f7c1d7f6..d809808de9 100644
--- a/sysdeps/unix/sysv/linux/loongarch/sysdep.S
+++ b/sysdeps/unix/sysv/linux/loongarch/sysdep.S
@@ -34,20 +34,20 @@  ENTRY (__syscall_set_errno)
 /* We got here because a0 < 0, but only codes in the range [-4095, -1]
    represent errors.  Otherwise, just return the result normally.
  */
-	li.d		t1, -4096
+	LI		t1, -4096
 	bgeu		t1, a0, L (out)
 	sub.w		a0, zero, a0
 #if RTLD_PRIVATE_ERRNO
 	la		t1, rtld_errno
 #elif defined(__PIC__)
 	la.tls.ie	t1, errno
-	add.d		t1, tp, t1
+	ADD		t1, tp, t1
 #else
 	la.tls.le	t1, errno
-	add.d		t1, tp, t1
+	ADD		t1, tp, t1
 #endif
 	st.w		a0, t1, 0
-	li.d		a0, -1
+	LI		a0, -1
 L (out):
 	ret
 END (__syscall_set_errno)
diff --git a/sysdeps/unix/sysv/linux/loongarch/sysdep.h b/sysdeps/unix/sysv/linux/loongarch/sysdep.h
index ac5b36f8c0..66afe496d9 100644
--- a/sysdeps/unix/sysv/linux/loongarch/sysdep.h
+++ b/sysdeps/unix/sysv/linux/loongarch/sysdep.h
@@ -34,9 +34,9 @@ 
 #undef PSEUDO
 #define PSEUDO(name, syscall_name, args) \
   ENTRY (name); \
-  li.d a7, SYS_ify (syscall_name); \
+  LI a7, SYS_ify (syscall_name); \
   syscall 0; \
-  li.d a7, -4096; \
+  LI a7, -4096; \
   bltu a7, a0, .Lsyscall_error##name;
 
 #undef PSEUDO_END
@@ -52,16 +52,16 @@ 
   .Lsyscall_error##name : la t0, rtld_errno; \
   sub.w a0, zero, a0; \
   st.w a0, t0, 0; \
-  li.d a0, -1;
+  LI a0, -1;
 
 #else
 
 #define SYSCALL_ERROR_HANDLER(name) \
   .Lsyscall_error##name : la.tls.ie t0, errno; \
-  add.d t0, tp, t0; \
+  ADD t0, tp, t0; \
   sub.w a0, zero, a0; \
   st.w a0, t0, 0; \
-  li.d a0, -1;
+  LI a0, -1;
 
 #endif
 #else
@@ -74,7 +74,7 @@ 
 #undef PSEUDO_NEORRNO
 #define PSEUDO_NOERRNO(name, syscall_name, args) \
   ENTRY (name); \
-  li.d a7, SYS_ify (syscall_name); \
+  LI a7, SYS_ify (syscall_name); \
   syscall 0;
 
 #undef PSEUDO_END_NOERRNO
@@ -85,11 +85,17 @@ 
 
 /* Performs a system call, returning the error code.  */
 #undef PSEUDO_ERRVAL
+#if __loongarch_grlen == 64
 #define PSEUDO_ERRVAL(name, syscall_name, args) \
   PSEUDO_NOERRNO (name, syscall_name, args); \
   slli.d a0, a0, 32; \
   srai.d a0, a0, 32; /* sign_ext */ \
   sub.d a0, zero, a0;
+#else
+#define PSEUDO_ERRVAL(name, syscall_name, args) \
+  PSEUDO_NOERRNO (name, syscall_name, args); \
+  sub.w a0, zero, a0;
+#endif
 
 #undef PSEUDO_END_ERRVAL
 #define PSEUDO_END_ERRVAL(name) END (name);
@@ -109,6 +115,18 @@ 
 #undef SYS_ify
 #define SYS_ify(syscall_name) __NR_##syscall_name
 
+#if __WORDSIZE == 32
+/* Workarounds for generic code needing to handle 64-bit time_t.  */
+#define __NR_clock_getres	__NR_clock_getres_time64
+#define __NR_futex		__NR_futex_time64
+#define __NR_ppoll		__NR_ppoll_time64
+#define __NR_pselect6		__NR_pselect6_time64
+#define __NR_recvmmsg		__NR_recvmmsg_time64
+#define __NR_rt_sigtimedwait	__NR_rt_sigtimedwait_time64
+#define __NR_semtimedop		__NR_semtimedop_time64
+#define __NR_utimensat		__NR_utimensat_time64
+#endif /* __WORDSIZE == 32 */
+
 #ifndef __ASSEMBLER__
 
 #define VDSO_NAME "LINUX_5.10"
diff --git a/sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h b/sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h
index 496d0d85e8..c5e0527300 100644
--- a/sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h
+++ b/sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h
@@ -23,10 +23,12 @@ 
 #include <sys/asm.h>
 #include "ucontext_i.h"
 
+/* mcontext_t.__gregs is unsigned long long on la32 and la64,
+   use 8 instead of SZREG.  */
 #define SAVE_INT_REG(name, num, base) \
-  REG_S name, base, ((num) *SZREG + MCONTEXT_GREGS)
+  REG_S name, base, ((num) * 8 + MCONTEXT_GREGS)
 
 #define RESTORE_INT_REG(name, num, base) \
-  REG_L name, base, ((num) *SZREG + MCONTEXT_GREGS)
+  REG_L name, base, ((num) * 8 + MCONTEXT_GREGS)
 
 #endif /* _LINUX_LOONGARCH_UCONTEXT_MACROS_H */
diff --git a/sysdeps/unix/sysv/linux/loongarch/vfork.S b/sysdeps/unix/sysv/linux/loongarch/vfork.S
index ab903f09d2..b450eac1f5 100644
--- a/sysdeps/unix/sysv/linux/loongarch/vfork.S
+++ b/sysdeps/unix/sysv/linux/loongarch/vfork.S
@@ -28,11 +28,11 @@ 
 
 ENTRY (__vfork)
 
-	li.d	a0, 0x4111 /* CLONE_VM | CLONE_VFORK | SIGCHLD */
-	add.d   a1, zero, sp
+	LI	a0, 0x4111 /* CLONE_VM | CLONE_VFORK | SIGCHLD */
+	ADD   a1, zero, sp
 
 	/* Do the system call.  */
-	li.d	a7, __NR_clone
+	LI	a7, __NR_clone
 	syscall	0
 
 	blt	a0, zero ,L (error)