@@ -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
@@ -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
@@ -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. */
@@ -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
@@ -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])
;;
@@ -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
@@ -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
@@ -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"_
similarity index 100%
rename from sysdeps/unix/sysv/linux/loongarch/arch-syscall.h
rename to sysdeps/unix/sysv/linux/loongarch/lp64/arch-syscall.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) \
@@ -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
@@ -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)
@@ -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
@@ -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)
@@ -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
@@ -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)
@@ -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"
@@ -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 */
@@ -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)