diff --git a/0082-LoongArch-add-new-relocs-and-fix-from-upstream.patch b/0082-LoongArch-add-new-relocs-and-fix-from-upstream.patch new file mode 100644 index 0000000..7e3fece --- /dev/null +++ b/0082-LoongArch-add-new-relocs-and-fix-from-upstream.patch @@ -0,0 +1,3327 @@ +From 711d9fa407fd05c18dcf864a6f3a676a26e0b47d Mon Sep 17 00:00:00 2001 +From: Peng Fan +Date: Mon, 3 Jul 2023 19:48:26 +0800 +Subject: [PATCH] LoongArch: add new relocs and fix from upstream + +Signed-off-by: Peng Fan +--- + elf/cache.c | 6 + + elf/elf.h | 49 +++++ + scripts/build-many-glibcs.py | 4 + + sysdeps/generic/ldconfig.h | 2 + + sysdeps/loongarch/Makefile | 14 +- + sysdeps/loongarch/__longjmp.S | 9 + + sysdeps/loongarch/bits/setjmp.h | 3 + + sysdeps/loongarch/configure | 98 +++++++++ + sysdeps/loongarch/configure.ac | 58 ++++++ + sysdeps/loongarch/dl-link.sym | 14 ++ + sysdeps/loongarch/dl-machine.h | 42 ++-- + sysdeps/loongarch/dl-trampoline.S | 186 +++++++++++++++++- + sysdeps/loongarch/fpu/e_ilogb.c | 39 ++++ + sysdeps/loongarch/fpu/e_ilogbf.c | 39 ++++ + sysdeps/loongarch/fpu/e_scalb.c | 60 ++++++ + sysdeps/loongarch/fpu/e_scalbf.c | 60 ++++++ + sysdeps/loongarch/fpu/get-rounding-mode.h | 38 ++++ + sysdeps/loongarch/fpu/math-barriers.h | 28 +++ + sysdeps/loongarch/fpu/math-use-builtins-fma.h | 4 + + .../loongarch/fpu/math-use-builtins-fmax.h | 10 + + .../loongarch/fpu/math-use-builtins-fmin.h | 10 + + .../loongarch/fpu/math-use-builtins-llrint.h | 10 + + .../loongarch/fpu/math-use-builtins-logb.h | 10 + + .../loongarch/fpu/math-use-builtins-lrint.h | 10 + + .../loongarch/fpu/math-use-builtins-rint.h | 9 + + sysdeps/loongarch/fpu/s_finite.c | 30 +++ + sysdeps/loongarch/fpu/s_finitef.c | 30 +++ + sysdeps/loongarch/fpu/s_fmaximum.c | 40 ++++ + sysdeps/loongarch/fpu/s_fmaximum_mag.c | 40 ++++ + sysdeps/loongarch/fpu/s_fmaximum_mag_num.c | 48 +++++ + sysdeps/loongarch/fpu/s_fmaximum_mag_numf.c | 48 +++++ + sysdeps/loongarch/fpu/s_fmaximum_magf.c | 40 ++++ + sysdeps/loongarch/fpu/s_fmaximum_num.c | 48 +++++ + sysdeps/loongarch/fpu/s_fmaximum_numf.c | 49 +++++ + sysdeps/loongarch/fpu/s_fmaximumf.c | 40 ++++ + sysdeps/loongarch/fpu/s_fmaxmag.c | 29 +++ + sysdeps/loongarch/fpu/s_fmaxmagf.c | 29 +++ + sysdeps/loongarch/fpu/s_fminimum.c | 40 ++++ + sysdeps/loongarch/fpu/s_fminimum_mag.c | 40 ++++ + sysdeps/loongarch/fpu/s_fminimum_mag_num.c | 48 +++++ + sysdeps/loongarch/fpu/s_fminimum_mag_numf.c | 48 +++++ + sysdeps/loongarch/fpu/s_fminimum_magf.c | 40 ++++ + sysdeps/loongarch/fpu/s_fminimum_num.c | 48 +++++ + sysdeps/loongarch/fpu/s_fminimum_numf.c | 48 +++++ + sysdeps/loongarch/fpu/s_fminimumf.c | 40 ++++ + sysdeps/loongarch/fpu/s_fminmag.c | 29 +++ + sysdeps/loongarch/fpu/s_fminmagf.c | 29 +++ + sysdeps/loongarch/fpu/s_fpclassify.c | 38 ++++ + sysdeps/loongarch/fpu/s_fpclassifyf.c | 38 ++++ + sysdeps/loongarch/fpu/s_isinf.c | 30 +++ + sysdeps/loongarch/fpu/s_isinff.c | 30 +++ + sysdeps/loongarch/fpu/s_isnan.c | 31 +++ + sysdeps/loongarch/fpu/s_isnanf.c | 31 +++ + sysdeps/loongarch/fpu/s_issignaling.c | 29 +++ + sysdeps/loongarch/fpu/s_issignalingf.c | 29 +++ + sysdeps/loongarch/fpu/s_scalbn.c | 29 +++ + sysdeps/loongarch/fpu/s_scalbnf.c | 29 +++ + sysdeps/loongarch/fpu_control.h | 30 +++ + sysdeps/loongarch/lp64/libm-test-ulps | 1 + + sysdeps/loongarch/nofpu/Implies | 1 + + .../loongarch/nofpu/math-tests-exceptions.h | 28 +++ + sysdeps/loongarch/nofpu/math-tests-rounding.h | 27 +++ + sysdeps/loongarch/preconfigure | 1 - + sysdeps/loongarch/preconfigure.ac | 1 - + sysdeps/loongarch/setjmp.S | 9 + + sysdeps/loongarch/start.S | 21 +- + sysdeps/loongarch/sys/asm.h | 1 + + sysdeps/unix/sysv/linux/loongarch/Makefile | 9 + + .../unix/sysv/linux/loongarch/bits/shmlba.h | 24 +++ + sysdeps/unix/sysv/linux/loongarch/configure | 51 ++++- + .../unix/sysv/linux/loongarch/configure.ac | 22 ++- + sysdeps/unix/sysv/linux/loongarch/dl-cache.h | 82 ++++++++ + .../unix/sysv/linux/loongarch/gettimeofday.c | 22 +++ + .../unix/sysv/linux/loongarch/ldd-rewrite.sed | 2 +- + .../unix/sysv/linux/loongarch/readelflib.c | 76 +++++++ + .../unix/sysv/linux/loongarch/shlib-versions | 2 + + sysdeps/unix/sysv/linux/loongarch/sysdep.h | 63 +++++- + sysdeps/unix/sysv/linux/syscall.c | 2 +- + 78 files changed, 2444 insertions(+), 38 deletions(-) + create mode 100644 sysdeps/loongarch/dl-link.sym + create mode 100644 sysdeps/loongarch/fpu/e_ilogb.c + create mode 100644 sysdeps/loongarch/fpu/e_ilogbf.c + create mode 100644 sysdeps/loongarch/fpu/e_scalb.c + create mode 100644 sysdeps/loongarch/fpu/e_scalbf.c + create mode 100644 sysdeps/loongarch/fpu/get-rounding-mode.h + create mode 100644 sysdeps/loongarch/fpu/math-barriers.h + create mode 100644 sysdeps/loongarch/fpu/math-use-builtins-fma.h + create mode 100644 sysdeps/loongarch/fpu/math-use-builtins-fmax.h + create mode 100644 sysdeps/loongarch/fpu/math-use-builtins-fmin.h + create mode 100644 sysdeps/loongarch/fpu/math-use-builtins-llrint.h + create mode 100644 sysdeps/loongarch/fpu/math-use-builtins-logb.h + create mode 100644 sysdeps/loongarch/fpu/math-use-builtins-lrint.h + create mode 100644 sysdeps/loongarch/fpu/math-use-builtins-rint.h + create mode 100644 sysdeps/loongarch/fpu/s_finite.c + create mode 100644 sysdeps/loongarch/fpu/s_finitef.c + create mode 100644 sysdeps/loongarch/fpu/s_fmaximum.c + create mode 100644 sysdeps/loongarch/fpu/s_fmaximum_mag.c + create mode 100644 sysdeps/loongarch/fpu/s_fmaximum_mag_num.c + create mode 100644 sysdeps/loongarch/fpu/s_fmaximum_mag_numf.c + create mode 100644 sysdeps/loongarch/fpu/s_fmaximum_magf.c + create mode 100644 sysdeps/loongarch/fpu/s_fmaximum_num.c + create mode 100644 sysdeps/loongarch/fpu/s_fmaximum_numf.c + create mode 100644 sysdeps/loongarch/fpu/s_fmaximumf.c + create mode 100644 sysdeps/loongarch/fpu/s_fmaxmag.c + create mode 100644 sysdeps/loongarch/fpu/s_fmaxmagf.c + create mode 100644 sysdeps/loongarch/fpu/s_fminimum.c + create mode 100644 sysdeps/loongarch/fpu/s_fminimum_mag.c + create mode 100644 sysdeps/loongarch/fpu/s_fminimum_mag_num.c + create mode 100644 sysdeps/loongarch/fpu/s_fminimum_mag_numf.c + create mode 100644 sysdeps/loongarch/fpu/s_fminimum_magf.c + create mode 100644 sysdeps/loongarch/fpu/s_fminimum_num.c + create mode 100644 sysdeps/loongarch/fpu/s_fminimum_numf.c + create mode 100644 sysdeps/loongarch/fpu/s_fminimumf.c + create mode 100644 sysdeps/loongarch/fpu/s_fminmag.c + create mode 100644 sysdeps/loongarch/fpu/s_fminmagf.c + create mode 100644 sysdeps/loongarch/fpu/s_fpclassify.c + create mode 100644 sysdeps/loongarch/fpu/s_fpclassifyf.c + create mode 100644 sysdeps/loongarch/fpu/s_isinf.c + create mode 100644 sysdeps/loongarch/fpu/s_isinff.c + create mode 100644 sysdeps/loongarch/fpu/s_isnan.c + create mode 100644 sysdeps/loongarch/fpu/s_isnanf.c + create mode 100644 sysdeps/loongarch/fpu/s_issignaling.c + create mode 100644 sysdeps/loongarch/fpu/s_issignalingf.c + create mode 100644 sysdeps/loongarch/fpu/s_scalbn.c + create mode 100644 sysdeps/loongarch/fpu/s_scalbnf.c + create mode 100644 sysdeps/loongarch/nofpu/Implies + create mode 100644 sysdeps/loongarch/nofpu/math-tests-exceptions.h + create mode 100644 sysdeps/loongarch/nofpu/math-tests-rounding.h + create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/shmlba.h + create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-cache.h + create mode 100644 sysdeps/unix/sysv/linux/loongarch/gettimeofday.c + create mode 100644 sysdeps/unix/sysv/linux/loongarch/readelflib.c + +diff --git a/elf/cache.c b/elf/cache.c +index 3d7d3a67..6f25b5a9 100644 +--- a/elf/cache.c ++++ b/elf/cache.c +@@ -229,6 +229,12 @@ print_entry (const char *lib, int flag, uint64_t hwcap, + case FLAG_RISCV_FLOAT_ABI_DOUBLE: + fputs (",double-float", stdout); + break; ++ case FLAG_LARCH_FLOAT_ABI_SOFT: ++ fputs (",soft-float", stdout); ++ break; ++ case FLAG_LARCH_FLOAT_ABI_DOUBLE: ++ fputs (",double-float", stdout); ++ break; + case 0: + break; + default: +diff --git a/elf/elf.h b/elf/elf.h +index 014393f3..ba54f754 100644 +--- a/elf/elf.h ++++ b/elf/elf.h +@@ -829,6 +829,15 @@ typedef struct + #define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers. */ + #define NT_MIPS_FP_MODE 0x801 /* MIPS floating-point mode. */ + #define NT_MIPS_MSA 0x802 /* MIPS SIMD registers. */ ++#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers. */ ++#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and ++ status registers. */ ++#define NT_LOONGARCH_LSX 0xa02 /* LoongArch Loongson SIMD ++ Extension registers. */ ++#define NT_LOONGARCH_LASX 0xa03 /* LoongArch Loongson Advanced ++ SIMD Extension registers. */ ++#define NT_LOONGARCH_LBT 0xa04 /* LoongArch Loongson Binary ++ Translation registers. */ + + /* Legal values for the note segment descriptor types for object files. */ + +@@ -4151,6 +4160,46 @@ enum + #define R_LARCH_GNU_VTINHERIT 57 + #define R_LARCH_GNU_VTENTRY 58 + ++/* reserved 59-63 */ ++ ++#define R_LARCH_B16 64 ++#define R_LARCH_B21 65 ++#define R_LARCH_B26 66 ++#define R_LARCH_ABS_HI20 67 ++#define R_LARCH_ABS_LO12 68 ++#define R_LARCH_ABS64_LO20 69 ++#define R_LARCH_ABS64_HI12 70 ++#define R_LARCH_PCALA_HI20 71 ++#define R_LARCH_PCALA_LO12 72 ++#define R_LARCH_PCALA64_LO20 73 ++#define R_LARCH_PCALA64_HI12 74 ++#define R_LARCH_GOT_PC_HI20 75 ++#define R_LARCH_GOT_PC_LO12 76 ++#define R_LARCH_GOT64_PC_LO20 77 ++#define R_LARCH_GOT64_PC_HI12 78 ++#define R_LARCH_GOT_HI20 79 ++#define R_LARCH_GOT_LO12 80 ++#define R_LARCH_GOT64_LO20 81 ++#define R_LARCH_GOT64_HI12 82 ++#define R_LARCH_TLS_LE_HI20 83 ++#define R_LARCH_TLS_LE_LO12 84 ++#define R_LARCH_TLS_LE64_LO20 85 ++#define R_LARCH_TLS_LE64_HI12 86 ++#define R_LARCH_TLS_IE_PC_HI20 87 ++#define R_LARCH_TLS_IE_PC_LO12 88 ++#define R_LARCH_TLS_IE64_PC_LO20 89 ++#define R_LARCH_TLS_IE64_PC_HI12 90 ++#define R_LARCH_TLS_IE_HI20 91 ++#define R_LARCH_TLS_IE_LO12 92 ++#define R_LARCH_TLS_IE64_LO20 93 ++#define R_LARCH_TLS_IE64_HI12 94 ++#define R_LARCH_TLS_LD_PC_HI20 95 ++#define R_LARCH_TLS_LD_HI20 96 ++#define R_LARCH_TLS_GD_PC_HI20 97 ++#define R_LARCH_TLS_GD_HI20 98 ++#define R_LARCH_32_PCREL 99 ++#define R_LARCH_RELAX 100 ++ + + /* ARCompact/ARCv2 specific relocs. */ + #define R_ARC_NONE 0x0 +diff --git a/scripts/build-many-glibcs.py b/scripts/build-many-glibcs.py +index da9b9059..1a130136 100755 +--- a/scripts/build-many-glibcs.py ++++ b/scripts/build-many-glibcs.py +@@ -222,6 +222,10 @@ class Context(object): + os_name='linux-gnu', + variant='lp64d', + gcc_cfg=['--with-abi=lp64d','--disable-multilib']) ++ self.add_config(arch='loongarch64', ++ os_name='linux-gnu', ++ variant='lp64s', ++ gcc_cfg=['--with-abi=lp64s','--disable-multilib']) + self.add_config(arch='m68k', + os_name='linux-gnu', + gcc_cfg=['--disable-multilib']) +diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h +index 7cc898db..4281372b 100644 +--- a/sysdeps/generic/ldconfig.h ++++ b/sysdeps/generic/ldconfig.h +@@ -45,6 +45,8 @@ + #define FLAG_MIPS64_LIBN64_NAN2008 0x0e00 + #define FLAG_RISCV_FLOAT_ABI_SOFT 0x0f00 + #define FLAG_RISCV_FLOAT_ABI_DOUBLE 0x1000 ++#define FLAG_LARCH_FLOAT_ABI_SOFT 0x1100 ++#define FLAG_LARCH_FLOAT_ABI_DOUBLE 0x1200 + + /* Name of auxiliary cache. */ + #define _PATH_LDCONFIG_AUX_CACHE "/var/cache/ldconfig/aux-cache" +diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile +index 41c34496..43d2f583 100644 +--- a/sysdeps/loongarch/Makefile ++++ b/sysdeps/loongarch/Makefile +@@ -2,14 +2,16 @@ ifeq ($(subdir),misc) + sysdep_headers += sys/asm.h + endif + ++ifeq ($(subdir),elf) ++gen-as-const-headers += dl-link.sym ++endif ++ + # LoongArch's assembler also needs to know about PIC as it changes the + # definition of some assembler macros. + ASFLAGS-.os += $(pic-ccflag) + +-abi-variants := lp64 +- +-ifeq (,$(filter $(default-abi),$(abi-variants))) +-$(error Unknown ABI $(default-abi), must be one of $(abi-variants)) ++# All the objects in lib*_nonshared.a need to be compiled with medium code ++# model or large applications may fail to link. ++ifeq (yes,$(have-cmodel-medium)) ++CFLAGS-.oS += -mcmodel=medium + endif +- +-abi-lp64-condition := defined __loongarch_lp64 +diff --git a/sysdeps/loongarch/__longjmp.S b/sysdeps/loongarch/__longjmp.S +index 37e73844..d6a99fcb 100644 +--- a/sysdeps/loongarch/__longjmp.S ++++ b/sysdeps/loongarch/__longjmp.S +@@ -20,8 +20,15 @@ + #include + + ENTRY (__longjmp) ++#ifdef PTR_MANGLE ++ REG_L t0, a0, 0*SZREG ++ PTR_DEMANGLE (ra, t0, t1) ++ REG_L t0, a0, 1*SZREG ++ PTR_DEMANGLE2 (sp, t0, t1) ++#else + REG_L ra, a0, 0*SZREG + REG_L sp, a0, 1*SZREG ++#endif + REG_L x, a0, 2*SZREG + REG_L fp, a0, 3*SZREG + REG_L s0, a0, 4*SZREG +@@ -34,6 +41,7 @@ ENTRY (__longjmp) + REG_L s7, a0, 11*SZREG + REG_L s8, a0, 12*SZREG + ++#ifndef __loongarch_soft_float + FREG_L $f24, a0, 13*SZREG + 0*SZFREG + FREG_L $f25, a0, 13*SZREG + 1*SZFREG + FREG_L $f26, a0, 13*SZREG + 2*SZFREG +@@ -42,6 +50,7 @@ ENTRY (__longjmp) + FREG_L $f29, a0, 13*SZREG + 5*SZFREG + FREG_L $f30, a0, 13*SZREG + 6*SZFREG + FREG_L $f31, a0, 13*SZREG + 7*SZFREG ++#endif + + sltui a0,a1,1 + ADD a0, a0, a1 # a0 = (a1 == 0) ? 1 : a1 +diff --git a/sysdeps/loongarch/bits/setjmp.h b/sysdeps/loongarch/bits/setjmp.h +index 42f8fa76..8b323ad2 100644 +--- a/sysdeps/loongarch/bits/setjmp.h ++++ b/sysdeps/loongarch/bits/setjmp.h +@@ -31,8 +31,11 @@ typedef struct __jmp_buf_internal_tag + long int __fp; + /* Callee-saved registers. */ + long int __regs[9]; ++ ++#ifndef __loongarch_soft_float + /* Callee-saved floating point registers. */ + double __fpregs[8]; ++#endif + + } __jmp_buf[1]; + +diff --git a/sysdeps/loongarch/configure b/sysdeps/loongarch/configure +index 43b54d49..b3c203ba 100644 +--- a/sysdeps/loongarch/configure ++++ b/sysdeps/loongarch/configure +@@ -3,3 +3,101 @@ + + $as_echo "#define HIDDEN_VAR_NEEDS_DYNAMIC_RELOC 1" >>confdefs.h + ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the toolchain is sufficient to build static PIE on LoongArch" >&5 ++$as_echo_n "checking if the toolchain is sufficient to build static PIE on LoongArch... " >&6; } ++if ${libc_cv_static_pie_on_loongarch+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ cat > conftest1.S << EOF ++.global _start ++.type _start, @function ++_start: ++ li.w \$a7, 93 ++ /* This ensures the assembler supports explicit reloc. */ ++ pcalau12i \$a0, %pc_hi20(x) ++ ld.w \$a0, \$a0, %pc_lo12(x) ++ syscall 0 ++ ++.data ++x: ++ .word 0 ++ /* This should produce an R_LARCH_RELATIVE in the static PIE. */ ++ .dword _start ++EOF ++ cat > conftest2.S << EOF ++.global f ++.type f, @function ++f: ++ /* The linker should be able to handle this and produce a PLT entry. */ ++ la.pcrel \$t0, \$t0, external_func ++ jirl \$zero, \$t0, 0 ++EOF ++ ++ libc_cv_static_pie_on_loongarch=no ++ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -static-pie -nostdlib -fPIE -o conftest1 conftest1.S' ++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } \ ++ && { ac_try='LC_ALL=C $READELF -Wr conftest1 | grep -q R_LARCH_RELATIVE' ++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } \ ++ && ! { ac_try='LC_ALL=C $READELF -Wl conftest1 | grep -q INTERP' ++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } \ ++ && { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -shared -fPIC -o conftest2.so conftest2.S' ++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } \ ++ && { ac_try='LC_ALL=C $READELF -Wr conftest2.so | grep -q 'R_LARCH_JUMP_SLOT.*external_func'' ++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } ++ then ++ libc_cv_static_pie_on_loongarch=yes ++ fi ++ rm -rf conftest* ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_static_pie_on_loongarch" >&5 ++$as_echo "$libc_cv_static_pie_on_loongarch" >&6; } ++ ++if test "$libc_cv_static_pie_on_loongarch" = yes; then ++ $as_echo "#define SUPPORT_STATIC_PIE 1" >>confdefs.h ++ ++fi ++ ++ # Check if gcc supports option -mcmodel=medium. ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports option -mcmodel=medium" >&5 ++$as_echo_n "checking whether $CC supports option -mcmodel=medium... " >&6; } ++if ${libc_cv_loongarch_cmodel_medium+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ++ if { ac_try='${CC-cc} -c $CFLAGS -mcmodel=medium /dev/null 1>&5' ++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; }; then ++ libc_cv_loongarch_cmodel_medium=yes ++ else ++ libc_cv_loongarch_cmodel_medium=no ++ fi ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_loongarch_cmodel_medium" >&5 ++$as_echo "$libc_cv_loongarch_cmodel_medium" >&6; } ++config_vars="$config_vars ++have-cmodel-medium = $libc_cv_loongarch_cmodel_medium" +diff --git a/sysdeps/loongarch/configure.ac b/sysdeps/loongarch/configure.ac +index f744367b..eaee4a9f 100644 +--- a/sysdeps/loongarch/configure.ac ++++ b/sysdeps/loongarch/configure.ac +@@ -4,3 +4,61 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. + dnl It is always possible to access static and hidden symbols in an + dnl position independent way. + AC_DEFINE(HIDDEN_VAR_NEEDS_DYNAMIC_RELOC) ++ ++dnl Test if the toolchain is new enough for static PIE. ++dnl We need a GAS supporting explicit reloc (older GAS produces stack-based ++dnl reloc and triggers an internal error in the linker). And, we need GCC to ++dnl pass the correct linker flags for static PIE. GCC >= 13 and GAS >= 2.40 ++dnl satisify the requirement, but a distro may backport static PIE support into ++dnl earlier GCC or Binutils releases as well. ++AC_CACHE_CHECK([if the toolchain is sufficient to build static PIE on LoongArch], ++libc_cv_static_pie_on_loongarch, [ ++ cat > conftest1.S << EOF ++.global _start ++.type _start, @function ++_start: ++ li.w \$a7, 93 ++ /* This ensures the assembler supports explicit reloc. */ ++ pcalau12i \$a0, %pc_hi20(x) ++ ld.w \$a0, \$a0, %pc_lo12(x) ++ syscall 0 ++ ++.data ++x: ++ .word 0 ++ /* This should produce an R_LARCH_RELATIVE in the static PIE. */ ++ .dword _start ++EOF ++ cat > conftest2.S << EOF ++.global f ++.type f, @function ++f: ++ /* The linker should be able to handle this and produce a PLT entry. */ ++ la.pcrel \$t0, \$t0, external_func ++ jirl \$zero, \$t0, 0 ++EOF ++ ++ libc_cv_static_pie_on_loongarch=no ++ if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -static-pie -nostdlib -fPIE -o conftest1 conftest1.S]) \ ++ && AC_TRY_COMMAND([LC_ALL=C $READELF -Wr conftest1 | grep -q R_LARCH_RELATIVE]) \ ++ && ! AC_TRY_COMMAND([LC_ALL=C $READELF -Wl conftest1 | grep -q INTERP]) \ ++ && AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -shared -fPIC -o conftest2.so conftest2.S]) \ ++ && AC_TRY_COMMAND([LC_ALL=C $READELF -Wr conftest2.so | grep -q 'R_LARCH_JUMP_SLOT.*external_func']) ++ then ++ libc_cv_static_pie_on_loongarch=yes ++ fi ++ rm -rf conftest* ]) ++ ++if test "$libc_cv_static_pie_on_loongarch" = yes; then ++ AC_DEFINE(SUPPORT_STATIC_PIE) ++fi ++ ++ # Check if gcc supports option -mcmodel=medium. ++AC_CACHE_CHECK(whether $CC supports option -mcmodel=medium, ++ libc_cv_loongarch_cmodel_medium, [ ++ if AC_TRY_COMMAND(${CC-cc} -c $CFLAGS -mcmodel=medium /dev/null 1>&AS_MESSAGE_LOG_FD); then ++ libc_cv_loongarch_cmodel_medium=yes ++ else ++ libc_cv_loongarch_cmodel_medium=no ++ fi]) ++LIBC_CONFIG_VAR([have-cmodel-medium], [$libc_cv_loongarch_cmodel_medium]) +diff --git a/sysdeps/loongarch/dl-link.sym b/sysdeps/loongarch/dl-link.sym +new file mode 100644 +index 00000000..868ab7c6 +--- /dev/null ++++ b/sysdeps/loongarch/dl-link.sym +@@ -0,0 +1,14 @@ ++#include ++#include ++#include ++ ++DL_SIZEOF_RG sizeof(struct La_loongarch_regs) ++DL_SIZEOF_RV sizeof(struct La_loongarch_retval) ++ ++DL_OFFSET_RG_A0 offsetof(struct La_loongarch_regs, lr_reg) ++DL_OFFSET_RG_FA0 offsetof(struct La_loongarch_regs, lr_fpreg) ++DL_OFFSET_RG_RA offsetof(struct La_loongarch_regs, lr_ra) ++DL_OFFSET_RG_SP offsetof(struct La_loongarch_regs, lr_sp) ++ ++DL_OFFSET_RV_A0 offsetof(struct La_loongarch_retval, lrv_a0) ++DL_OFFSET_RV_FA0 offsetof(struct La_loongarch_retval, lrv_a1) +diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h +index c69c72d0..516d2421 100644 +--- a/sysdeps/loongarch/dl-machine.h ++++ b/sysdeps/loongarch/dl-machine.h +@@ -166,8 +166,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[], + { + + case R_LARCH_JUMP_SLOT: +- case __WORDSIZE == 64 ? R_LARCH_64: +- R_LARCH_32: ++ case __WORDSIZE == 64 ? R_LARCH_64 : R_LARCH_32: + *addr_field = value; + break; + +@@ -175,18 +174,15 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[], + break; + + #ifndef RTLD_BOOTSTRAP +- case __WORDSIZE == 64 ? R_LARCH_TLS_DTPMOD64: +- R_LARCH_TLS_DTPMOD32: ++ case __WORDSIZE == 64 ? R_LARCH_TLS_DTPMOD64 : R_LARCH_TLS_DTPMOD32: + *addr_field = sym_map->l_tls_modid; + break; + +- case __WORDSIZE == 64 ? R_LARCH_TLS_DTPREL64: +- R_LARCH_TLS_DTPREL32: ++ case __WORDSIZE == 64 ? R_LARCH_TLS_DTPREL64 : R_LARCH_TLS_DTPREL32: + *addr_field = TLS_DTPREL_VALUE (sym) + reloc->r_addend; + break; + +- case __WORDSIZE == 64 ? R_LARCH_TLS_TPREL64: +- R_LARCH_TLS_TPREL32: ++ case __WORDSIZE == 64 ? R_LARCH_TLS_TPREL64 : R_LARCH_TLS_TPREL32: + CHECK_STATIC_TLS (map, sym_map); + *addr_field = TLS_TPREL_VALUE (sym_map, sym) + reloc->r_addend; + break; +@@ -274,10 +270,34 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], + /* If using PLTs, fill in the first two entries of .got.plt. */ + if (l->l_info[DT_JMPREL]) + { +- extern void _dl_runtime_resolve (void) +- __attribute__ ((visibility ("hidden"))); ++ extern void _dl_runtime_resolve (void) attribute_hidden; ++ extern void _dl_runtime_profile (void) attribute_hidden; ++ + ElfW (Addr) *gotplt = (ElfW (Addr) *) D_PTR (l, l_info[DT_PLTGOT]); +- gotplt[0] = (ElfW (Addr)) & _dl_runtime_resolve; ++ ++ /* The got[0] entry contains the address of a function which gets ++ called to get the address of a so far unresolved function and ++ jump to it. The profiling extension of the dynamic linker allows ++ to intercept the calls to collect information. In this case we ++ don't store the address in the GOT so that all future calls also ++ end in this function. */ ++ if (profile != 0) ++ { ++ gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile; ++ ++ if (GLRO(dl_profile) != NULL ++ && _dl_name_match_p (GLRO(dl_profile), l)) ++ /* Say that we really want profiling and the timers are ++ started. */ ++ GL(dl_profile_map) = l; ++ } ++ else ++ { ++ /* This function will get called to fix up the GOT entry ++ indicated by the offset on the stack, and then jump to ++ the resolved address. */ ++ gotplt[0] = (ElfW (Addr)) & _dl_runtime_resolve; ++ } + gotplt[1] = (ElfW (Addr)) l; + } + #endif +diff --git a/sysdeps/loongarch/dl-trampoline.S b/sysdeps/loongarch/dl-trampoline.S +index ad8ab0fd..f9070e8e 100644 +--- a/sysdeps/loongarch/dl-trampoline.S ++++ b/sysdeps/loongarch/dl-trampoline.S +@@ -19,16 +19,20 @@ + #include + #include + ++#include "dl-link.h" ++ + /* Assembler veneer called from the PLT header code for lazy loading. + The PLT header passes its own args in t0-t2. */ +- +-# define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK)) ++#ifdef __loongarch_soft_float ++#define FRAME_SIZE (-((-10 * SZREG) & ALMASK)) ++#else ++#define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK)) ++#endif + + ENTRY (_dl_runtime_resolve) + + /* Save arguments to stack. */ + ADDI sp, sp, -FRAME_SIZE +- + REG_S ra, sp, 9*SZREG + REG_S a0, sp, 1*SZREG + REG_S a1, sp, 2*SZREG +@@ -39,6 +43,7 @@ ENTRY (_dl_runtime_resolve) + REG_S a6, sp, 7*SZREG + REG_S a7, sp, 8*SZREG + ++#ifndef __loongarch_soft_float + FREG_S fa0, sp, 10*SZREG + 0*SZFREG + FREG_S fa1, sp, 10*SZREG + 1*SZFREG + FREG_S fa2, sp, 10*SZREG + 2*SZFREG +@@ -47,6 +52,7 @@ ENTRY (_dl_runtime_resolve) + FREG_S fa5, sp, 10*SZREG + 5*SZFREG + FREG_S fa6, sp, 10*SZREG + 6*SZFREG + FREG_S fa7, sp, 10*SZREG + 7*SZFREG ++#endif + + /* Update .got.plt and obtain runtime address of callee */ + SLLI a1, t1, 1 +@@ -67,6 +73,7 @@ ENTRY (_dl_runtime_resolve) + REG_L a6, sp, 7*SZREG + REG_L a7, sp, 8*SZREG + ++#ifndef __loongarch_soft_float + FREG_L fa0, sp, 10*SZREG + 0*SZFREG + FREG_L fa1, sp, 10*SZREG + 1*SZFREG + FREG_L fa2, sp, 10*SZREG + 2*SZFREG +@@ -75,9 +82,182 @@ ENTRY (_dl_runtime_resolve) + FREG_L fa5, sp, 10*SZREG + 5*SZFREG + FREG_L fa6, sp, 10*SZREG + 6*SZFREG + FREG_L fa7, sp, 10*SZREG + 7*SZFREG ++#endif + + ADDI sp, sp, FRAME_SIZE + + /* Invoke the callee. */ + jirl zero, t1, 0 + END (_dl_runtime_resolve) ++ ++ ++ENTRY (_dl_runtime_profile) ++ /* LoongArch we get called with: ++ t0 linkr_map pointer ++ t1 the scaled offset stored in t0, which can be used ++ to calculate the offset of the current symbol in .rela.plt ++ t2 %hi(%pcrel(.got.plt)) stored in t2, no use in this function ++ t3 dl resolver entry point, no use in this function ++ ++ Stack frame layout: ++ [sp, #96] La_loongarch_regs ++ [sp, #48] La_loongarch_retval ++ [sp, #40] frame size return from pltenter ++ [sp, #32] dl_profile_call saved a1 ++ [sp, #24] dl_profile_call saved a0 ++ [sp, #16] T1 ++ [sp, #0] ra, fp <- fp ++ */ ++ ++# define OFFSET_T1 16 ++# define OFFSET_SAVED_CALL_A0 OFFSET_T1 + 8 ++# define OFFSET_FS OFFSET_SAVED_CALL_A0 + 16 ++# define OFFSET_RV OFFSET_FS + 8 ++# define OFFSET_RG OFFSET_RV + DL_SIZEOF_RV ++ ++# define SF_SIZE (-(-(OFFSET_RG + DL_SIZEOF_RG) & ALMASK)) ++ ++ /* Save arguments to stack. */ ++ ADDI sp, sp, -SF_SIZE ++ REG_S ra, sp, 0 ++ REG_S fp, sp, 8 ++ ++ or fp, sp, zero ++ ++ REG_S a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG ++ REG_S a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG ++ REG_S a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG ++ REG_S a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG ++ REG_S a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG ++ REG_S a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG ++ REG_S a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG ++ REG_S a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG ++ ++#ifndef __loongarch_soft_float ++ FREG_S fa0, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 0*SZFREG ++ FREG_S fa1, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 1*SZFREG ++ FREG_S fa2, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 2*SZFREG ++ FREG_S fa3, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 3*SZFREG ++ FREG_S fa4, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 4*SZFREG ++ FREG_S fa5, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 5*SZFREG ++ FREG_S fa6, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 6*SZFREG ++ FREG_S fa7, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 7*SZFREG ++#endif ++ ++ /* Update .got.plt and obtain runtime address of callee. */ ++ SLLI a1, t1, 1 ++ or a0, t0, zero ++ ADD a1, a1, t1 ++ or a2, ra, zero /* return addr */ ++ ADDI a3, fp, OFFSET_RG /* La_loongarch_regs pointer */ ++ ADDI a4, fp, OFFSET_FS /* frame size return from pltenter */ ++ ++ REG_S a0, fp, OFFSET_SAVED_CALL_A0 ++ REG_S a1, fp, OFFSET_SAVED_CALL_A0 + SZREG ++ ++ la t2, _dl_profile_fixup ++ jirl ra, t2, 0 ++ ++ REG_L t3, fp, OFFSET_FS ++ bge t3, zero, 1f ++ ++ /* Save the return. */ ++ or t4, v0, zero ++ ++ /* Restore arguments from stack. */ ++ REG_L a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG ++ REG_L a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG ++ REG_L a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG ++ REG_L a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG ++ REG_L a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG ++ REG_L a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG ++ REG_L a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG ++ REG_L a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG ++ ++#ifndef __loongarch_soft_float ++ FREG_L fa0, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 0*SZFREG ++ FREG_L fa1, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 1*SZFREG ++ FREG_L fa2, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 2*SZFREG ++ FREG_L fa3, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 3*SZFREG ++ FREG_L fa4, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 4*SZFREG ++ FREG_L fa5, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 5*SZFREG ++ FREG_L fa6, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 6*SZFREG ++ FREG_L fa7, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 7*SZFREG ++#endif ++ ++ REG_L ra, fp, 0 ++ REG_L fp, fp, SZREG ++ ++ ADDI sp, sp, SF_SIZE ++ jirl zero, t4, 0 ++ ++1: ++ /* The new frame size is in t3. */ ++ SUB sp, fp, t3 ++ BSTRINS sp, zero, 3, 0 ++ ++ REG_S a0, fp, OFFSET_T1 ++ ++ or a0, sp, zero ++ ADDI a1, fp, SF_SIZE ++ or a2, t3, zero ++ la t5, memcpy ++ jirl ra, t5, 0 ++ ++ REG_L t6, fp, OFFSET_T1 ++ ++ /* Call the function. */ ++ REG_L a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG ++ REG_L a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG ++ REG_L a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG ++ REG_L a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG ++ REG_L a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG ++ REG_L a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG ++ REG_L a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG ++ REG_L a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG ++ ++#ifndef __loongarch_soft_float ++ FREG_L fa0, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 0*SZFREG ++ FREG_L fa1, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 1*SZFREG ++ FREG_L fa2, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 2*SZFREG ++ FREG_L fa3, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 3*SZFREG ++ FREG_L fa4, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 4*SZFREG ++ FREG_L fa5, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 5*SZFREG ++ FREG_L fa6, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 6*SZFREG ++ FREG_L fa7, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 7*SZFREG ++#endif ++ jirl ra, t6, 0 ++ ++ REG_S a0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_A0 ++ REG_S a1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_A0 + SZREG ++ ++#ifndef __loongarch_soft_float ++ FREG_S fa0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_FA0 ++ FREG_S fa1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_FA0 + SZFREG ++#endif ++ ++ /* Setup call to pltexit. */ ++ REG_L a0, fp, OFFSET_SAVED_CALL_A0 ++ REG_L a1, fp, OFFSET_SAVED_CALL_A0 + SZREG ++ ADDI a2, fp, OFFSET_RG ++ ADDI a3, fp, OFFSET_RV ++ la t7, _dl_audit_pltexit ++ jirl ra, t7, 0 ++ ++ REG_L a0, fp, OFFSET_RV + DL_OFFSET_RV_A0 ++ REG_L a1, fp, OFFSET_RV + DL_OFFSET_RV_A0 + SZREG ++ ++#ifndef __loongarch_soft_float ++ FREG_L fa0, fp, OFFSET_RV + DL_OFFSET_RV_FA0 ++ FREG_L fa1, fp, OFFSET_RV + DL_OFFSET_RV_FA0 + SZFREG ++#endif ++ ++ /* RA from within La_loongarch_reg. */ ++ REG_L ra, fp, OFFSET_RG + DL_OFFSET_RG_RA ++ or sp, fp, zero ++ ADDI sp, sp, SF_SIZE ++ REG_S fp, fp, SZREG ++ ++ jirl zero, ra, 0 ++ ++END (_dl_runtime_profile) +diff --git a/sysdeps/loongarch/fpu/e_ilogb.c b/sysdeps/loongarch/fpu/e_ilogb.c +new file mode 100644 +index 00000000..f9ada692 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/e_ilogb.c +@@ -0,0 +1,39 @@ ++/* __ieee754_ilogb(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++ ++int ++__ieee754_ilogb (double x) ++{ ++ int x_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ ++ if (__glibc_unlikely (x_cond & _FCLASS_ZERO)) ++ return FP_ILOGB0; ++ else if (__glibc_unlikely (x_cond & ( _FCLASS_NAN | _FCLASS_INF))) ++ return FP_ILOGBNAN; ++ else ++ { ++ asm volatile ("fabs.d \t%0, %1" : "=f" (x) : "f" (x)); ++ asm volatile ("flogb.d \t%0, %1" : "=f" (x) : "f" (x)); ++ return x; ++ } ++} +diff --git a/sysdeps/loongarch/fpu/e_ilogbf.c b/sysdeps/loongarch/fpu/e_ilogbf.c +new file mode 100644 +index 00000000..e1da48ec +--- /dev/null ++++ b/sysdeps/loongarch/fpu/e_ilogbf.c +@@ -0,0 +1,39 @@ ++/* __ieee754_ilogbf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++ ++int ++__ieee754_ilogbf (float x) ++{ ++ int x_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ ++ if (__glibc_unlikely (x_cond & _FCLASS_ZERO)) ++ return FP_ILOGB0; ++ else if (__glibc_unlikely (x_cond & ( _FCLASS_NAN | _FCLASS_INF))) ++ return FP_ILOGBNAN; ++ else ++ { ++ asm volatile ("fabs.s \t%0, %1" : "=f" (x) : "f" (x)); ++ asm volatile ("flogb.s \t%0, %1" : "=f" (x) : "f" (x)); ++ return x; ++ } ++} +diff --git a/sysdeps/loongarch/fpu/e_scalb.c b/sysdeps/loongarch/fpu/e_scalb.c +new file mode 100644 +index 00000000..9fdf21fa +--- /dev/null ++++ b/sysdeps/loongarch/fpu/e_scalb.c +@@ -0,0 +1,60 @@ ++/* scalb(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++#include ++ ++double ++__ieee754_scalb (double x, double fn) ++{ ++ int x_cond; ++ int fn_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.d \t%0, %1" : "=f" (fn_cond) : "f" (fn)); ++ ++ if (__glibc_unlikely(( x_cond | fn_cond) & _FCLASS_NAN)) ++ return x * fn; ++ else if (__glibc_unlikely(fn_cond & _FCLASS_INF)) ++ { ++ if (!(fn_cond & _FCLASS_MINF)) ++ return x * fn; ++ else ++ return x / -fn; ++ } ++ else if (__glibc_likely(-DBL_MAX < fn && fn < DBL_MAX)) ++ { ++ double rint_fn, tmp; ++ ++ /* rint_fn = rint(fn) */ ++ asm volatile ("frint.d \t%0, %1" : "=f" (rint_fn) : "f" (fn)); ++ ++ if (rint_fn != fn ) ++ return (x - x) / (x - x); ++ ++ asm volatile ("ftintrz.l.d \t%0, %1" : "=f" (tmp) : "f" (rint_fn)); ++ asm volatile ("fscaleb.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (tmp)); ++ } ++ else ++ asm volatile ("fscaleb.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (fn)); ++ ++ return x; ++} ++libm_alias_finite (__ieee754_scalb, __scalb) +diff --git a/sysdeps/loongarch/fpu/e_scalbf.c b/sysdeps/loongarch/fpu/e_scalbf.c +new file mode 100644 +index 00000000..fae2e92e +--- /dev/null ++++ b/sysdeps/loongarch/fpu/e_scalbf.c +@@ -0,0 +1,60 @@ ++/* scalbf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++#include ++ ++float ++__ieee754_scalbf (float x, float fn) ++{ ++ int x_cond; ++ int fn_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.s \t%0, %1" : "=f" (fn_cond) : "f" (fn)); ++ ++ if (__glibc_unlikely(( x_cond | fn_cond) & _FCLASS_NAN)) ++ return x * fn; ++ else if (__glibc_unlikely(fn_cond & _FCLASS_INF)) ++ { ++ if (!(fn_cond & _FCLASS_MINF)) ++ return x * fn; ++ else ++ return x / -fn; ++ } ++ else if (__glibc_likely(-FLT_MAX < fn && fn < FLT_MAX)) ++ { ++ float rintf_fn, tmp; ++ ++ /* rintf_fn = rintf(fn) */ ++ asm volatile ("frint.s \t%0, %1" : "=f" (rintf_fn) : "f" (fn)); ++ ++ if (rintf_fn != fn ) ++ return (x - x) / (x - x); ++ ++ asm volatile ("ftintrz.w.s \t%0, %1" : "=f" (tmp) : "f" (rintf_fn)); ++ asm volatile ("fscaleb.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (tmp)); ++ } ++ else ++ asm volatile ("fscaleb.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (fn)); ++ ++ return x; ++} ++libm_alias_finite (__ieee754_scalb, __scalb) +diff --git a/sysdeps/loongarch/fpu/get-rounding-mode.h b/sysdeps/loongarch/fpu/get-rounding-mode.h +new file mode 100644 +index 00000000..b60733e2 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/get-rounding-mode.h +@@ -0,0 +1,38 @@ ++/* Determine floating-point rounding mode within libc. LoongArch version. ++ ++ Copyright (C) 2022-2023 Free Software Foundation, Inc. ++ ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _LARCH_GET_ROUNDING_MODE_H ++#define _LARCH_GET_ROUNDING_MODE_H 1 ++ ++#include ++#include ++ ++/* Return the floating-point rounding mode. */ ++ ++static inline int ++get_rounding_mode (void) ++{ ++ fpu_control_t fpcr; ++ ++ _FPU_GETCW (fpcr); ++ return fpcr & _FPU_RC_MASK; ++} ++ ++#endif /* get-rounding-mode.h */ +diff --git a/sysdeps/loongarch/fpu/math-barriers.h b/sysdeps/loongarch/fpu/math-barriers.h +new file mode 100644 +index 00000000..3e977e43 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/math-barriers.h +@@ -0,0 +1,28 @@ ++/* Control when floating-point expressions are evaluated. LoongArch version. ++ Copyright (C) 2023 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _LOONGARCH_MATH_BARRIERS_H ++#define _LOONGARCH_MATH_BARRIERS_H 1 ++ ++/* Generic code forces values to memory; we don't need to do that. */ ++#define math_opt_barrier(x) \ ++ ({ __typeof (x) __x = (x); __asm ("" : "+frm" (__x)); __x; }) ++#define math_force_eval(x) \ ++ ({ __typeof (x) __x = (x); __asm __volatile__ ("" : : "frm" (__x)); }) ++ ++#endif /* math-barriers.h */ +diff --git a/sysdeps/loongarch/fpu/math-use-builtins-fma.h b/sysdeps/loongarch/fpu/math-use-builtins-fma.h +new file mode 100644 +index 00000000..eede75aa +--- /dev/null ++++ b/sysdeps/loongarch/fpu/math-use-builtins-fma.h +@@ -0,0 +1,4 @@ ++#define USE_FMA_BUILTIN 1 ++#define USE_FMAF_BUILTIN 1 ++#define USE_FMAL_BUILTIN 0 ++#define USE_FMAF128_BUILTIN 0 +diff --git a/sysdeps/loongarch/fpu/math-use-builtins-fmax.h b/sysdeps/loongarch/fpu/math-use-builtins-fmax.h +new file mode 100644 +index 00000000..5d22567b +--- /dev/null ++++ b/sysdeps/loongarch/fpu/math-use-builtins-fmax.h +@@ -0,0 +1,10 @@ ++#if __GNUC_PREREQ (13, 0) ++# define USE_FMAX_BUILTIN 1 ++# define USE_FMAXF_BUILTIN 1 ++#else ++# define USE_FMAX_BUILTIN 0 ++# define USE_FMAXF_BUILTIN 0 ++#endif ++ ++#define USE_FMAXL_BUILTIN 0 ++#define USE_FMAXF128_BUILTIN 0 +diff --git a/sysdeps/loongarch/fpu/math-use-builtins-fmin.h b/sysdeps/loongarch/fpu/math-use-builtins-fmin.h +new file mode 100644 +index 00000000..4d28b41c +--- /dev/null ++++ b/sysdeps/loongarch/fpu/math-use-builtins-fmin.h +@@ -0,0 +1,10 @@ ++#if __GNUC_PREREQ (13, 0) ++# define USE_FMIN_BUILTIN 1 ++# define USE_FMINF_BUILTIN 1 ++#else ++# define USE_FMIN_BUILTIN 0 ++# define USE_FMINF_BUILTIN 0 ++#endif ++ ++#define USE_FMINL_BUILTIN 0 ++#define USE_FMINF128_BUILTIN 0 +diff --git a/sysdeps/loongarch/fpu/math-use-builtins-llrint.h b/sysdeps/loongarch/fpu/math-use-builtins-llrint.h +new file mode 100644 +index 00000000..bee5910b +--- /dev/null ++++ b/sysdeps/loongarch/fpu/math-use-builtins-llrint.h +@@ -0,0 +1,10 @@ ++#if __GNUC_PREREQ (13, 0) ++# define USE_LLRINT_BUILTIN 1 ++# define USE_LLRINTF_BUILTIN 1 ++#else ++# define USE_LLRINT_BUILTIN 0 ++# define USE_LLRINTF_BUILTIN 0 ++#endif ++ ++#define USE_LLRINTL_BUILTIN 0 ++#define USE_LLRINTF128_BUILTIN 0 +diff --git a/sysdeps/loongarch/fpu/math-use-builtins-logb.h b/sysdeps/loongarch/fpu/math-use-builtins-logb.h +new file mode 100644 +index 00000000..b1c3f30d +--- /dev/null ++++ b/sysdeps/loongarch/fpu/math-use-builtins-logb.h +@@ -0,0 +1,10 @@ ++#if __GNUC_PREREQ (13, 0) ++# define USE_LOGB_BUILTIN 1 ++# define USE_LOGBF_BUILTIN 1 ++#else ++# define USE_LOGB_BUILTIN 0 ++# define USE_LOGBF_BUILTIN 0 ++#endif ++ ++#define USE_LOGBL_BUILTIN 0 ++#define USE_LOGBF128_BUILTIN 0 +diff --git a/sysdeps/loongarch/fpu/math-use-builtins-lrint.h b/sysdeps/loongarch/fpu/math-use-builtins-lrint.h +new file mode 100644 +index 00000000..7df8aac8 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/math-use-builtins-lrint.h +@@ -0,0 +1,10 @@ ++#if __GNUC_PREREQ (13, 0) ++# define USE_LRINT_BUILTIN 1 ++# define USE_LRINTF_BUILTIN 1 ++#else ++# define USE_LRINT_BUILTIN 0 ++# define USE_LRINTF_BUILTIN 0 ++#endif ++ ++#define USE_LRINTL_BUILTIN 0 ++#define USE_LRINTF128_BUILTIN 0 +diff --git a/sysdeps/loongarch/fpu/math-use-builtins-rint.h b/sysdeps/loongarch/fpu/math-use-builtins-rint.h +new file mode 100644 +index 00000000..cd91482f +--- /dev/null ++++ b/sysdeps/loongarch/fpu/math-use-builtins-rint.h +@@ -0,0 +1,9 @@ ++#if __GNUC_PREREQ (13, 0) ++# define USE_RINT_BUILTIN 1 ++# define USE_RINTF_BUILTIN 1 ++#else ++# define USE_RINT_BUILTIN 0 ++# define USE_RINTF_BUILTIN 0 ++#endif ++#define USE_RINTL_BUILTIN 0 ++#define USE_RINTF128_BUILTIN 0 +diff --git a/sysdeps/loongarch/fpu/s_finite.c b/sysdeps/loongarch/fpu/s_finite.c +new file mode 100644 +index 00000000..a2e98f0b +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_finite.c +@@ -0,0 +1,30 @@ ++/* finite(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#include ++#include ++ ++int ++__finite (double x) ++{ ++ int x_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ return x_cond & ~(_FCLASS_INF | _FCLASS_NAN); ++} ++hidden_def (__finite) ++weak_alias (__finite, finite) +diff --git a/sysdeps/loongarch/fpu/s_finitef.c b/sysdeps/loongarch/fpu/s_finitef.c +new file mode 100644 +index 00000000..9ffab38a +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_finitef.c +@@ -0,0 +1,30 @@ ++/* finitef(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#include ++#include ++ ++int ++__finitef (float x) ++{ ++ int x_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ return x_cond & ~(_FCLASS_INF | _FCLASS_NAN); ++} ++hidden_def (__finitef) ++weak_alias (__finitef, finitef) +diff --git a/sysdeps/loongarch/fpu/s_fmaximum.c b/sysdeps/loongarch/fpu/s_fmaximum.c +new file mode 100644 +index 00000000..af1c2bf0 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fmaximum.c +@@ -0,0 +1,40 @@ ++/* fmaximum(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++double ++__fmaximum (double x, double y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.d \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond | y_cond) & _FCLASS_NAN)) ++ return x * y; ++ else ++ { ++ asm volatile ("fmax.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_double (__fmaximum, fmaximum) +diff --git a/sysdeps/loongarch/fpu/s_fmaximum_mag.c b/sysdeps/loongarch/fpu/s_fmaximum_mag.c +new file mode 100644 +index 00000000..5aed0603 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fmaximum_mag.c +@@ -0,0 +1,40 @@ ++/* fmaximum_mag(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++double ++__fmaximum_mag (double x, double y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.d \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond | y_cond) & _FCLASS_NAN)) ++ return x * y; ++ else ++ { ++ asm volatile ("fmaxa.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_double (__fmaximum_mag, fmaximum_mag) +diff --git a/sysdeps/loongarch/fpu/s_fmaximum_mag_num.c b/sysdeps/loongarch/fpu/s_fmaximum_mag_num.c +new file mode 100644 +index 00000000..04c801b1 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fmaximum_mag_num.c +@@ -0,0 +1,48 @@ ++/* fmaximum_mag_num(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++double ++__fmaximum_mag_num (double x, double y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.d \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond & _FCLASS_NAN) && !(y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmaxa.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return y; ++ } ++ else if (__glibc_unlikely(!(x_cond & _FCLASS_NAN) && (y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmaxa.d \t%0, %1, %2" : "=f" (y) : "f" (x), "f" (y)); ++ return x; ++ } ++ else ++ { ++ asm volatile ("fmaxa.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_double (__fmaximum_mag_num, fmaximum_mag_num) +diff --git a/sysdeps/loongarch/fpu/s_fmaximum_mag_numf.c b/sysdeps/loongarch/fpu/s_fmaximum_mag_numf.c +new file mode 100644 +index 00000000..a2e1aaf1 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fmaximum_mag_numf.c +@@ -0,0 +1,48 @@ ++/* fmaximum_mag_numf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++float ++__fmaximum_mag_numf (float x, float y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.s \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond & _FCLASS_NAN) && !(y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmaxa.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return y; ++ } ++ else if (__glibc_unlikely(!(x_cond & _FCLASS_NAN) && (y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmaxa.s \t%0, %1, %2" : "=f" (y) : "f" (x), "f" (y)); ++ return x; ++ } ++ else ++ { ++ asm volatile ("fmaxa.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_float (__fmaximum_mag_num, fmaximum_mag_num) +diff --git a/sysdeps/loongarch/fpu/s_fmaximum_magf.c b/sysdeps/loongarch/fpu/s_fmaximum_magf.c +new file mode 100644 +index 00000000..29beb88c +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fmaximum_magf.c +@@ -0,0 +1,40 @@ ++/* fmaximum_magf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++float ++__fmaximum_magf (float x, float y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.s \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond | y_cond) & _FCLASS_NAN)) ++ return x * y; ++ else ++ { ++ asm volatile ("fmaxa.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_float (__fmaximum_mag, fmaximum_mag) +diff --git a/sysdeps/loongarch/fpu/s_fmaximum_num.c b/sysdeps/loongarch/fpu/s_fmaximum_num.c +new file mode 100644 +index 00000000..142c6533 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fmaximum_num.c +@@ -0,0 +1,48 @@ ++/* fmaximum_num(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++double ++__fmaximum_num (double x, double y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.d \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond & _FCLASS_NAN) && !(y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmax.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return y; ++ } ++ else if (__glibc_unlikely(!(x_cond & _FCLASS_NAN) && (y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmax.d \t%0, %1, %2" : "=f" (y) : "f" (x), "f" (y)); ++ return x; ++ } ++ else ++ { ++ asm volatile ("fmax.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_double (__fmaximum_num, fmaximum_num) +diff --git a/sysdeps/loongarch/fpu/s_fmaximum_numf.c b/sysdeps/loongarch/fpu/s_fmaximum_numf.c +new file mode 100644 +index 00000000..badf8f7e +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fmaximum_numf.c +@@ -0,0 +1,49 @@ ++/* fmaximum_numf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++float ++__fmaximum_numf (float x, float y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.s \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond & _FCLASS_NAN) && !(y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmax.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return y; ++ } ++ else if (__glibc_unlikely(!(x_cond & _FCLASS_NAN) && (y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmax.s \t%0, %1, %2" : "=f" (y) : "f" (x), "f" (y)); ++ return x; ++ } ++ else ++ { ++ asm volatile ("fmax.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_float (__fmaximum_num, fmaximum_num) +diff --git a/sysdeps/loongarch/fpu/s_fmaximumf.c b/sysdeps/loongarch/fpu/s_fmaximumf.c +new file mode 100644 +index 00000000..da4dcb6a +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fmaximumf.c +@@ -0,0 +1,40 @@ ++/* fmaximumf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++float ++__fmaximumf (float x, float y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.s \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond | y_cond) & _FCLASS_NAN)) ++ return x * y; ++ else ++ { ++ asm volatile ("fmax.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_float (__fmaximum, fmaximum) +diff --git a/sysdeps/loongarch/fpu/s_fmaxmag.c b/sysdeps/loongarch/fpu/s_fmaxmag.c +new file mode 100644 +index 00000000..8570a3ba +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fmaxmag.c +@@ -0,0 +1,29 @@ ++/* fmaxmag(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++ ++double ++__fmaxmag (double x, double y) ++{ ++ asm volatile ("fmaxa.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++} ++libm_alias_double (__fmaxmag, fmaxmag) +diff --git a/sysdeps/loongarch/fpu/s_fmaxmagf.c b/sysdeps/loongarch/fpu/s_fmaxmagf.c +new file mode 100644 +index 00000000..413e7683 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fmaxmagf.c +@@ -0,0 +1,29 @@ ++/* fmaxmagf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++ ++float ++__fmaxmagf (float x, float y) ++{ ++ asm volatile ("fmaxa.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++} ++libm_alias_float (__fmaxmag, fmaxmag) +diff --git a/sysdeps/loongarch/fpu/s_fminimum.c b/sysdeps/loongarch/fpu/s_fminimum.c +new file mode 100644 +index 00000000..e395ff7e +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fminimum.c +@@ -0,0 +1,40 @@ ++/* fminimum(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++double ++__fminimum (double x, double y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.d \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond | y_cond) & _FCLASS_NAN)) ++ return x * y; ++ else ++ { ++ asm volatile ("fmin.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_double (__fminimum, fminimum) +diff --git a/sysdeps/loongarch/fpu/s_fminimum_mag.c b/sysdeps/loongarch/fpu/s_fminimum_mag.c +new file mode 100644 +index 00000000..f477498d +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fminimum_mag.c +@@ -0,0 +1,40 @@ ++/* fminimum_mag(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++double ++__fminimum_mag (double x, double y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.d \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond | y_cond) & _FCLASS_NAN)) ++ return x * y; ++ else ++ { ++ asm volatile ("fmina.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_double (__fminimum_mag, fminimum_mag) +diff --git a/sysdeps/loongarch/fpu/s_fminimum_mag_num.c b/sysdeps/loongarch/fpu/s_fminimum_mag_num.c +new file mode 100644 +index 00000000..ff5aecd6 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fminimum_mag_num.c +@@ -0,0 +1,48 @@ ++/* fminimum_mag_num(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++double ++__fminimum_mag_num (double x, double y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.d \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond & _FCLASS_NAN) && !(y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmina.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return y; ++ } ++ else if (__glibc_unlikely(!(x_cond & _FCLASS_NAN) && (y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmina.d \t%0, %1, %2" : "=f" (y) : "f" (x), "f" (y)); ++ return x; ++ } ++ else ++ { ++ asm volatile ("fmina.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_double (__fminimum_mag_num, fminimum_mag_num) +diff --git a/sysdeps/loongarch/fpu/s_fminimum_mag_numf.c b/sysdeps/loongarch/fpu/s_fminimum_mag_numf.c +new file mode 100644 +index 00000000..7c9a5dba +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fminimum_mag_numf.c +@@ -0,0 +1,48 @@ ++/* fminimum_mag_numf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++float ++__fminimum_mag_numf (float x, float y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.s \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond & _FCLASS_NAN) && !(y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmina.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return y; ++ } ++ else if (__glibc_unlikely(!(x_cond & _FCLASS_NAN) && (y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmina.s \t%0, %1, %2" : "=f" (y) : "f" (x), "f" (y)); ++ return x; ++ } ++ else ++ { ++ asm volatile ("fmina.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_float (__fminimum_mag_num, fminimum_mag_num) +diff --git a/sysdeps/loongarch/fpu/s_fminimum_magf.c b/sysdeps/loongarch/fpu/s_fminimum_magf.c +new file mode 100644 +index 00000000..d0563fc2 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fminimum_magf.c +@@ -0,0 +1,40 @@ ++/* fminimum_magf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++float ++__fminimum_magf (float x, float y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.s \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond | y_cond) & _FCLASS_NAN)) ++ return x * y; ++ else ++ { ++ asm volatile ("fmina.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_float (__fminimum_mag, fminimum_mag) +diff --git a/sysdeps/loongarch/fpu/s_fminimum_num.c b/sysdeps/loongarch/fpu/s_fminimum_num.c +new file mode 100644 +index 00000000..5d9680be +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fminimum_num.c +@@ -0,0 +1,48 @@ ++/* fminimum_num(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++double ++__fminimum_num (double x, double y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.d \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond & _FCLASS_NAN) && !(y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmin.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return y; ++ } ++ else if (__glibc_unlikely(!(x_cond & _FCLASS_NAN) && (y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmin.d \t%0, %1, %2" : "=f" (y) : "f" (x), "f" (y)); ++ return x; ++ } ++ else ++ { ++ asm volatile ("fmin.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_double (__fminimum_num, fminimum_num) +diff --git a/sysdeps/loongarch/fpu/s_fminimum_numf.c b/sysdeps/loongarch/fpu/s_fminimum_numf.c +new file mode 100644 +index 00000000..1610fe32 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fminimum_numf.c +@@ -0,0 +1,48 @@ ++/* fminimum_numf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++float ++__fminimum_numf (float x, float y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.s \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond & _FCLASS_NAN) && !(y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmin.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return y; ++ } ++ else if (__glibc_unlikely(!(x_cond & _FCLASS_NAN) && (y_cond & _FCLASS_NAN))) ++ { ++ asm volatile ("fmin.s \t%0, %1, %2" : "=f" (y) : "f" (x), "f" (y)); ++ return x; ++ } ++ else ++ { ++ asm volatile ("fmin.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_float (__fminimum_num, fminimum_num) +diff --git a/sysdeps/loongarch/fpu/s_fminimumf.c b/sysdeps/loongarch/fpu/s_fminimumf.c +new file mode 100644 +index 00000000..680c5e7e +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fminimumf.c +@@ -0,0 +1,40 @@ ++/* fminimumf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++float ++__fminimumf (float x, float y) ++{ ++ int x_cond; ++ int y_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ asm volatile ("fclass.s \t%0, %1" : "=f" (y_cond) : "f" (y)); ++ ++ if (__glibc_unlikely((x_cond | y_cond) & _FCLASS_NAN)) ++ return x * y; ++ else ++ { ++ asm volatile ("fmin.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++ } ++} ++libm_alias_float (__fminimum, fminimum) +diff --git a/sysdeps/loongarch/fpu/s_fminmag.c b/sysdeps/loongarch/fpu/s_fminmag.c +new file mode 100644 +index 00000000..2badf3d3 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fminmag.c +@@ -0,0 +1,29 @@ ++/* fminmag(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++ ++double ++__fminmag (double x, double y) ++{ ++ asm volatile ("fmina.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++} ++libm_alias_double (__fminmag, fminmag) +diff --git a/sysdeps/loongarch/fpu/s_fminmagf.c b/sysdeps/loongarch/fpu/s_fminmagf.c +new file mode 100644 +index 00000000..4d625312 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fminmagf.c +@@ -0,0 +1,29 @@ ++/* fminmagf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++ ++float ++__fminmagf (float x, float y) ++{ ++ asm volatile ("fmina.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (y)); ++ return x; ++} ++libm_alias_float (__fminmag, fminmag) +diff --git a/sysdeps/loongarch/fpu/s_fpclassify.c b/sysdeps/loongarch/fpu/s_fpclassify.c +new file mode 100644 +index 00000000..3f4d95da +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fpclassify.c +@@ -0,0 +1,38 @@ ++/* fpclassify(). LoongArch version. ++ Copyright (C) 2017-2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#include ++#include ++ ++int ++__fpclassify (double x) ++{ ++ int cls; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (cls) : "f" (x)); ++ ++ if (__glibc_likely (!!(cls & _FCLASS_NORM))) ++ return FP_NORMAL; ++ if (__glibc_likely (!!(cls & _FCLASS_ZERO))) ++ return FP_ZERO; ++ if (__glibc_likely (!!(cls & _FCLASS_SUBNORM))) ++ return FP_SUBNORMAL; ++ if (__glibc_likely (!!(cls & _FCLASS_INF))) ++ return FP_INFINITE; ++ return FP_NAN; ++} ++libm_hidden_def (__fpclassify) +diff --git a/sysdeps/loongarch/fpu/s_fpclassifyf.c b/sysdeps/loongarch/fpu/s_fpclassifyf.c +new file mode 100644 +index 00000000..b7c8b253 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_fpclassifyf.c +@@ -0,0 +1,38 @@ ++/* Copyright (C) 2017-2022 Free Software Foundation, Inc. ++ ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#include ++#include ++ ++int ++__fpclassifyf (float x) ++{ ++ int cls; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (cls) : "f" (x)); ++ ++ if (__glibc_likely (!!(cls & _FCLASS_NORM))) ++ return FP_NORMAL; ++ if (__glibc_likely (!!(cls & _FCLASS_ZERO))) ++ return FP_ZERO; ++ if (__glibc_likely (!!(cls & _FCLASS_SUBNORM))) ++ return FP_SUBNORMAL; ++ if (__glibc_likely (!!(cls & _FCLASS_INF))) ++ return FP_INFINITE; ++ return FP_NAN; ++} ++libm_hidden_def (__fpclassifyf) +diff --git a/sysdeps/loongarch/fpu/s_isinf.c b/sysdeps/loongarch/fpu/s_isinf.c +new file mode 100644 +index 00000000..c7a67841 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_isinf.c +@@ -0,0 +1,30 @@ ++/* isinf(). LoongArch version. ++ Copyright (C) 2017-2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#include ++#include ++ ++int ++__isinf (double x) ++{ ++ int x_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ return -((x_cond & _FCLASS_MINF) ? 1 : 0) | ((x_cond & _FCLASS_PINF) ? 1 : 0); ++} ++hidden_def (__isinf) ++weak_alias (__isinf, isinf) +diff --git a/sysdeps/loongarch/fpu/s_isinff.c b/sysdeps/loongarch/fpu/s_isinff.c +new file mode 100644 +index 00000000..dcb4e04e +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_isinff.c +@@ -0,0 +1,30 @@ ++/* isinff(). LoongArch version. ++ Copyright (C) 2017-2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#include ++#include ++ ++int ++__isinff (float x) ++{ ++ int x_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ return -((x_cond & _FCLASS_MINF) ? 1 : 0) | ((x_cond & _FCLASS_PINF) ? 1 : 0); ++} ++hidden_def (__isinff) ++weak_alias (__isinff, isinff) +diff --git a/sysdeps/loongarch/fpu/s_isnan.c b/sysdeps/loongarch/fpu/s_isnan.c +new file mode 100644 +index 00000000..62bb2e2f +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_isnan.c +@@ -0,0 +1,31 @@ ++/* isnan(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#include ++#include ++ ++int ++__isnan (double x) ++{ ++ int x_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ ++ return (x_cond & _FCLASS_NAN) != 0; ++} ++hidden_def (__isnan) ++weak_alias (__isnan, isnan) +diff --git a/sysdeps/loongarch/fpu/s_isnanf.c b/sysdeps/loongarch/fpu/s_isnanf.c +new file mode 100644 +index 00000000..bbdedb84 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_isnanf.c +@@ -0,0 +1,31 @@ ++/* isnanf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#include ++#include ++ ++int ++__isnanf (float x) ++{ ++ int x_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ ++ return (x_cond & _FCLASS_NAN) != 0; ++} ++hidden_def (__isnanf) ++weak_alias (__isnanf, isnanf) +diff --git a/sysdeps/loongarch/fpu/s_issignaling.c b/sysdeps/loongarch/fpu/s_issignaling.c +new file mode 100644 +index 00000000..4fe0e2b7 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_issignaling.c +@@ -0,0 +1,29 @@ ++/* issignaling(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#include ++#include ++ ++int ++__issignaling (double x) ++{ ++ int x_cond; ++ asm volatile ("fclass.d \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ return (x_cond & _FCLASS_SNAN) != 0; ++} ++libm_hidden_def (__issignaling) +diff --git a/sysdeps/loongarch/fpu/s_issignalingf.c b/sysdeps/loongarch/fpu/s_issignalingf.c +new file mode 100644 +index 00000000..d82abb0e +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_issignalingf.c +@@ -0,0 +1,29 @@ ++/* issignalingf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#include ++#include ++ ++int ++__issignalingf (float x) ++{ ++ int x_cond; ++ asm volatile ("fclass.s \t%0, %1" : "=f" (x_cond) : "f" (x)); ++ return (x_cond & _FCLASS_SNAN) != 0; ++} ++libm_hidden_def (__issignalingf) +diff --git a/sysdeps/loongarch/fpu/s_scalbn.c b/sysdeps/loongarch/fpu/s_scalbn.c +new file mode 100644 +index 00000000..c03e81a3 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_scalbn.c +@@ -0,0 +1,29 @@ ++/* scalbn(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++ ++double ++__scalbn (double x, int fn) ++{ ++ double tmp; ++ asm volatile ("movgr2fr.d \t%0, %1" : "=f" (tmp) : "r" (fn)); ++ asm volatile ("fscaleb.d \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (tmp)); ++ return x; ++} +diff --git a/sysdeps/loongarch/fpu/s_scalbnf.c b/sysdeps/loongarch/fpu/s_scalbnf.c +new file mode 100644 +index 00000000..15e64280 +--- /dev/null ++++ b/sysdeps/loongarch/fpu/s_scalbnf.c +@@ -0,0 +1,29 @@ ++/* scalbnf(). LoongArch version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define NO_MATH_REDIRECT ++#include ++ ++float ++__scalbnf (float x, int fn) ++{ ++ float tmp; ++ asm volatile ("movgr2fr.w \t%0, %1" : "=f" (tmp) : "r" (fn)); ++ asm volatile ("fscaleb.s \t%0, %1, %2" : "=f" (x) : "f" (x), "f" (tmp)); ++ return x; ++} +diff --git a/sysdeps/loongarch/fpu_control.h b/sysdeps/loongarch/fpu_control.h +index 1cccc933..13436335 100644 +--- a/sysdeps/loongarch/fpu_control.h ++++ b/sysdeps/loongarch/fpu_control.h +@@ -51,6 +51,17 @@ + + #include + ++#ifdef __loongarch_soft_float ++ ++#define _FPU_RESERVED 0xffffffff ++#define _FPU_DEFAULT 0x00000000 ++typedef unsigned int fpu_control_t; ++#define _FPU_GETCW(cw) (cw) = 0 ++#define _FPU_SETCW(cw) (void) (cw) ++extern fpu_control_t __fpu_control; ++ ++#else /* __loongarch_soft_float */ ++ + /* Masks for interrupts. */ + #define _FPU_MASK_V 0x10 /* Invalid operation */ + #define _FPU_MASK_Z 0x08 /* Division by zero */ +@@ -86,4 +97,23 @@ extern void __loongarch_fpu_setcw (fpu_control_t) __THROW; + /* Default control word set at startup. */ + extern fpu_control_t __fpu_control; + ++# define _FCLASS_SNAN (1 << 0) ++# define _FCLASS_QNAN (1 << 1) ++# define _FCLASS_MINF (1 << 2) ++# define _FCLASS_MNORM (1 << 3) ++# define _FCLASS_MSUBNORM (1 << 4) ++# define _FCLASS_MZERO (1 << 5) ++# define _FCLASS_PINF (1 << 6) ++# define _FCLASS_PNORM (1 << 7) ++# define _FCLASS_PSUBNORM (1 << 8) ++# define _FCLASS_PZERO (1 << 9) ++ ++# define _FCLASS_ZERO (_FCLASS_MZERO | _FCLASS_PZERO) ++# define _FCLASS_SUBNORM (_FCLASS_MSUBNORM | _FCLASS_PSUBNORM) ++# define _FCLASS_NORM (_FCLASS_MNORM | _FCLASS_PNORM) ++# define _FCLASS_INF (_FCLASS_MINF | _FCLASS_PINF) ++# define _FCLASS_NAN (_FCLASS_SNAN | _FCLASS_QNAN) ++ ++#endif /* __loongarch_soft_float */ ++ + #endif /* fpu_control.h */ +diff --git a/sysdeps/loongarch/lp64/libm-test-ulps b/sysdeps/loongarch/lp64/libm-test-ulps +index c711531e..770bf36b 100644 +--- a/sysdeps/loongarch/lp64/libm-test-ulps ++++ b/sysdeps/loongarch/lp64/libm-test-ulps +@@ -1046,6 +1046,7 @@ ldouble: 8 + + Function: "hypot": + double: 1 ++float: 1 + ldouble: 1 + + Function: "hypot_downward": +diff --git a/sysdeps/loongarch/nofpu/Implies b/sysdeps/loongarch/nofpu/Implies +new file mode 100644 +index 00000000..abcbadb2 +--- /dev/null ++++ b/sysdeps/loongarch/nofpu/Implies +@@ -0,0 +1 @@ ++ieee754/soft-fp +diff --git a/sysdeps/loongarch/nofpu/math-tests-exceptions.h b/sysdeps/loongarch/nofpu/math-tests-exceptions.h +new file mode 100644 +index 00000000..b22bb01d +--- /dev/null ++++ b/sysdeps/loongarch/nofpu/math-tests-exceptions.h +@@ -0,0 +1,28 @@ ++/* Configuration for math tests: support for exceptions. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef LOONGARCH_NOFPU_MATH_TESTS_EXCEPTIONS_H ++#define LOONGARCH_NOFPU_MATH_TESTS_EXCEPTIONS_H 1 ++ ++/* We support setting floating-point exception flags on hard-float ++ targets. These are not supported on soft-float targets. */ ++#define EXCEPTION_TESTS_float 0 ++#define EXCEPTION_TESTS_double 0 ++#define EXCEPTION_TESTS_long_double 0 ++ ++#endif /* math-tests-exceptions.h. */ +diff --git a/sysdeps/loongarch/nofpu/math-tests-rounding.h b/sysdeps/loongarch/nofpu/math-tests-rounding.h +new file mode 100644 +index 00000000..5322e481 +--- /dev/null ++++ b/sysdeps/loongarch/nofpu/math-tests-rounding.h +@@ -0,0 +1,27 @@ ++/* Configuration for math tests: rounding mode support. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef LOONGARCH_NOFPU_MATH_TESTS_ROUNDING_H ++#define LOONGARCH_NOFPU_MATH_TESTS_ROUNDING_H 1 ++ ++/* On soft-float targets we only support the "to nearest" rounding mode. */ ++#define ROUNDING_TESTS_float(MODE) ((MODE) == FE_TONEAREST) ++#define ROUNDING_TESTS_double(MODE) ((MODE) == FE_TONEAREST) ++#define ROUNDING_TESTS_long_double(MODE) ((MODE) == FE_TONEAREST) ++ ++#endif /* math-tests-rounding.h. */ +diff --git a/sysdeps/loongarch/preconfigure b/sysdeps/loongarch/preconfigure +index 118963cd..f2d1a0d8 100644 +--- a/sysdeps/loongarch/preconfigure ++++ b/sysdeps/loongarch/preconfigure +@@ -12,7 +12,6 @@ loongarch*) + case "$float_abi" in + soft) + abi_flen=0 +- as_fn_error 1 "loongarch does not yet support soft floating-point ABI!!" "$LINENO" 5 + ;; + single) + as_fn_error 1 "glibc does not yet support the single floating-point ABI!!" "$LINENO" 5 +diff --git a/sysdeps/loongarch/preconfigure.ac b/sysdeps/loongarch/preconfigure.ac +index 1aba743c..67e43570 100644 +--- a/sysdeps/loongarch/preconfigure.ac ++++ b/sysdeps/loongarch/preconfigure.ac +@@ -12,7 +12,6 @@ loongarch*) + case "$float_abi" in + soft) + abi_flen=0 +- AC_MSG_ERROR([loongarch does not yet support soft floating-point ABI!!], 1) + ;; + single) + AC_MSG_ERROR([glibc does not yet support the single floating-point ABI!!], 1) +diff --git a/sysdeps/loongarch/setjmp.S b/sysdeps/loongarch/setjmp.S +index 3afb9f39..9b1cdea4 100644 +--- a/sysdeps/loongarch/setjmp.S ++++ b/sysdeps/loongarch/setjmp.S +@@ -29,8 +29,15 @@ ENTRY (setjmp) + END (setjmp) + + ENTRY (__sigsetjmp) ++#ifdef PTR_MANGLE ++ PTR_MANGLE (t0, ra, t1) ++ REG_S t0, a0, 0*SZREG ++ PTR_MANGLE2 (t0, sp, t1) ++ REG_S t0, a0, 1*SZREG ++#else + REG_S ra, a0, 0*SZREG + REG_S sp, a0, 1*SZREG ++#endif + REG_S x, a0, 2*SZREG + REG_S fp, a0, 3*SZREG + REG_S s0, a0, 4*SZREG +@@ -43,6 +50,7 @@ ENTRY (__sigsetjmp) + REG_S s7, a0, 11*SZREG + REG_S s8, a0, 12*SZREG + ++#ifndef __loongarch_soft_float + FREG_S $f24, a0, 13*SZREG + 0*SZFREG + FREG_S $f25, a0, 13*SZREG + 1*SZFREG + FREG_S $f26, a0, 13*SZREG + 2*SZFREG +@@ -51,6 +59,7 @@ ENTRY (__sigsetjmp) + FREG_S $f29, a0, 13*SZREG + 5*SZFREG + FREG_S $f30, a0, 13*SZREG + 6*SZFREG + FREG_S $f31, a0, 13*SZREG + 7*SZFREG ++#endif + + #if !IS_IN (libc) && IS_IN(rtld) + li.w v0, 0 +diff --git a/sysdeps/loongarch/start.S b/sysdeps/loongarch/start.S +index bf5728b3..83aeacb1 100644 +--- a/sysdeps/loongarch/start.S ++++ b/sysdeps/loongarch/start.S +@@ -44,9 +44,20 @@ ENTRY (ENTRY_POINT) + cfi_undefined (1) + or a5, a0, zero /* rtld_fini */ + +-/* We must get symbol main through GOT table, since main may not be local. +- For instance: googletest defines main in dynamic library. */ +- la.got a0, t0, main ++#if ENABLE_STATIC_PIE ++/* For static PIE, the GOT cannot be used in _start because the GOT entries are ++ offsets instead of real addresses before __libc_start_main. ++ __libc_start_main and/or main may be not local, so we rely on the linker to ++ produce PLT entries for them. GNU ld >= 2.40 supports this. */ ++# define LA la.pcrel ++#else ++/* Old GNU ld (< 2.40) cannot handle PC relative address against a non-local ++ function correctly. We deem these old linkers failing to support static PIE ++ and load the addresses from GOT. */ ++# define LA la.got ++#endif ++ ++ LA a0, t0, main + REG_L a1, sp, 0 + ADDI a2, sp, SZREG + +@@ -57,9 +68,9 @@ ENTRY (ENTRY_POINT) + move a4, zero /* used to be fini */ + or a6, sp, zero /* stack_end */ + +- la.got ra, t0, __libc_start_main ++ LA ra, t0, __libc_start_main + jirl ra, ra, 0 + +- la.got ra, t0, abort ++ LA ra, t0, abort + jirl ra, ra, 0 + END (ENTRY_POINT) +diff --git a/sysdeps/loongarch/sys/asm.h b/sysdeps/loongarch/sys/asm.h +index b41ee596..83ee3f67 100644 +--- a/sysdeps/loongarch/sys/asm.h ++++ b/sysdeps/loongarch/sys/asm.h +@@ -31,6 +31,7 @@ + #define SLLI slli.d + #define ADDI addi.d + #define ADD add.d ++#define SUB sub.d + #define BSTRINS bstrins.d + #define LI li.d + #define FREG_L fld.d +diff --git a/sysdeps/unix/sysv/linux/loongarch/Makefile b/sysdeps/unix/sysv/linux/loongarch/Makefile +index 91bd3580..c84a1762 100644 +--- a/sysdeps/unix/sysv/linux/loongarch/Makefile ++++ b/sysdeps/unix/sysv/linux/loongarch/Makefile +@@ -1,3 +1,12 @@ + ifeq ($(subdir),stdlib) + gen-as-const-headers += ucontext_i.sym + endif ++ ++abi-variants := lp64s lp64d ++ ++ifeq (,$(filter $(default-abi),$(abi-variants))) ++$(error Unknown ABI $(default-abi), must be one of $(abi-variants)) ++endif ++ ++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/bits/shmlba.h b/sysdeps/unix/sysv/linux/loongarch/bits/shmlba.h +new file mode 100644 +index 00000000..3c171ef7 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/loongarch/bits/shmlba.h +@@ -0,0 +1,24 @@ ++/* Define SHMLBA. LoongArch version. ++ Copyright (C) 2023 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _SYS_SHM_H ++# error "Never use directly; include instead." ++#endif ++ ++/* Segment low boundary address multiple. */ ++#define SHMLBA 0x10000 +diff --git a/sysdeps/unix/sysv/linux/loongarch/configure b/sysdeps/unix/sysv/linux/loongarch/configure +index 60a41030..28216c16 100644 +--- a/sysdeps/unix/sysv/linux/loongarch/configure ++++ b/sysdeps/unix/sysv/linux/loongarch/configure +@@ -151,11 +151,56 @@ if test $libc_cv_loongarch_int_abi = no; then + as_fn_error $? "Unable to determine integer ABI" "$LINENO" 5 + fi + ++libc_cv_loongarch_float_abi=no ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#ifdef __loongarch_double_float ++ yes ++ #endif ++ ++_ACEOF ++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | ++ $EGREP "yes" >/dev/null 2>&1; then : ++ libc_cv_loongarch_float_abi=d ++fi ++rm -f conftest* ++ ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++#ifdef __loongarch_soft_float ++ yes ++ #endif ++ ++_ACEOF ++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | ++ $EGREP "yes" >/dev/null 2>&1; then : ++ libc_cv_loongarch_float_abi=s ++fi ++rm -f conftest* ++ ++if test "$libc_cv_loongarch_float_abi" = no; then ++ as_fn_error $? "Unable to determine floating-point ABI" "$LINENO" 5 ++fi ++ + config_vars="$config_vars +-default-abi = $libc_cv_loongarch_int_abi" ++default-abi = $libc_cv_loongarch_int_abi$libc_cv_loongarch_float_abi" + +-case $libc_cv_loongarch_int_abi in +-lp64) ++case $libc_cv_loongarch_int_abi$libc_cv_loongarch_float_abi in ++lp64s) ++ test -n "$libc_cv_slibdir" || ++case "$prefix" in ++/usr | /usr/) ++ libc_cv_slibdir='/lib64/sf' ++ libc_cv_rtlddir='/lib64' ++ if test "$libdir" = '${exec_prefix}/lib'; then ++ libdir='${exec_prefix}/lib64/sf'; ++ # Locale data can be shared between 32-bit and 64-bit libraries. ++ libc_cv_complocaledir='${exec_prefix}/lib/locale' ++ fi ++ ;; ++esac ++ ;; ++lp64d) + test -n "$libc_cv_slibdir" || + case "$prefix" in + /usr | /usr/) +diff --git a/sysdeps/unix/sysv/linux/loongarch/configure.ac b/sysdeps/unix/sysv/linux/loongarch/configure.ac +index 7de1e95f..04e9150a 100644 +--- a/sysdeps/unix/sysv/linux/loongarch/configure.ac ++++ b/sysdeps/unix/sysv/linux/loongarch/configure.ac +@@ -11,10 +11,26 @@ if test $libc_cv_loongarch_int_abi = no; then + AC_MSG_ERROR([Unable to determine integer ABI]) + fi + +-LIBC_CONFIG_VAR([default-abi], [$libc_cv_loongarch_int_abi]) ++libc_cv_loongarch_float_abi=no ++AC_EGREP_CPP(yes, [#ifdef __loongarch_double_float ++ yes ++ #endif ++ ],libc_cv_loongarch_float_abi=d) ++AC_EGREP_CPP(yes, [#ifdef __loongarch_soft_float ++ yes ++ #endif ++ ],libc_cv_loongarch_float_abi=s) ++if test "$libc_cv_loongarch_float_abi" = no; then ++ AC_MSG_ERROR([Unable to determine floating-point ABI]) ++fi ++ ++LIBC_CONFIG_VAR([default-abi], [$libc_cv_loongarch_int_abi$libc_cv_loongarch_float_abi]) + +-case $libc_cv_loongarch_int_abi in +-lp64) ++case $libc_cv_loongarch_int_abi$libc_cv_loongarch_float_abi in ++lp64s) ++ LIBC_SLIBDIR_RTLDDIR([lib64/sf], [lib64]) ++ ;; ++lp64d) + LIBC_SLIBDIR_RTLDDIR([lib64], [lib64]) + ;; + esac +diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-cache.h b/sysdeps/unix/sysv/linux/loongarch/dl-cache.h +new file mode 100644 +index 00000000..05219c62 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/loongarch/dl-cache.h +@@ -0,0 +1,82 @@ ++/* Support for reading /etc/ld.so.cache files written by Linux ldconfig. ++ Copyright (C) 2022-2023 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#include ++#include ++ ++#if defined __loongarch_double_float ++# define _DL_CACHE_DEFAULT_ID (FLAG_LARCH_FLOAT_ABI_DOUBLE | FLAG_ELF_LIBC6) ++#else ++# define _DL_CACHE_DEFAULT_ID (FLAG_LARCH_FLOAT_ABI_SOFT | FLAG_ELF_LIBC6) ++#endif ++ ++#define _dl_cache_check_flags(flags) \ ++ ((flags) == _DL_CACHE_DEFAULT_ID) ++ ++/* If given a path to one of our library directories, adds every library ++ directory via add_dir (), otherwise just adds the giver directory. On ++ LoongArch, libraries can be found in paths ending in: ++ - /lib64 ++ - /lib64/sf ++ so this will add all of those paths. */ ++ ++#define add_system_dir(dir) \ ++ do \ ++ { \ ++ static const char* lib_dirs[] = { \ ++ "/lib64", \ ++ "/lib64/sf", \ ++ NULL, \ ++ }; \ ++ const size_t lib_len = sizeof ("/lib") - 1; \ ++ size_t len = strlen (dir); \ ++ char path[len + 6]; \ ++ const char **ptr; \ ++ \ ++ memcpy (path, dir, len + 1); \ ++ \ ++ for (ptr = lib_dirs; *ptr != NULL; ptr++) \ ++ { \ ++ const char *lib_dir = *ptr; \ ++ size_t dir_len = strlen (lib_dir); \ ++ \ ++ if (len >= dir_len \ ++ && !memcmp (path + len - dir_len, lib_dir, dir_len)) \ ++ { \ ++ len -= dir_len - lib_len; \ ++ path[len] = '\0'; \ ++ break; \ ++ } \ ++ } \ ++ add_dir (path); \ ++ if (len >= lib_len \ ++ && !memcmp (path + len - lib_len, "/lib", lib_len)) \ ++ for (ptr = lib_dirs; *ptr != NULL; ptr++) \ ++ { \ ++ const char *lib_dir = *ptr; \ ++ size_t dir_len = strlen (lib_dir); \ ++ \ ++ assert (dir_len >= lib_len); \ ++ memcpy (path + len, lib_dir + lib_len, \ ++ dir_len - lib_len + 1); \ ++ add_dir (path); \ ++ } \ ++ } while (0) ++ ++ ++#include_next +diff --git a/sysdeps/unix/sysv/linux/loongarch/gettimeofday.c b/sysdeps/unix/sysv/linux/loongarch/gettimeofday.c +new file mode 100644 +index 00000000..ee35a086 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/loongarch/gettimeofday.c +@@ -0,0 +1,22 @@ ++/* gettimeofday -- Get the current time of day. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++ ++#define USE_IFUNC_GETTIMEOFDAY ++#include +diff --git a/sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed b/sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed +index f8976fd2..cdbe5c3d 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\)\(/[^/]*\)\(-loongarch\)\(64\|32\)\(\.so\.[0-9.]*\)[[:blank:]]*$_\1"\2\4\7 \264\4-loongarch64\7 \232\4-loongarch32\7"_ ++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"_ +diff --git a/sysdeps/unix/sysv/linux/loongarch/readelflib.c b/sysdeps/unix/sysv/linux/loongarch/readelflib.c +new file mode 100644 +index 00000000..e3461289 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/loongarch/readelflib.c +@@ -0,0 +1,76 @@ ++/* Support for reading ELF files. ++ Copyright (C) 2022-2023 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++ ++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); ++ ++#define SUPPORTED_ELF_FLAGS \ ++ (EF_LARCH_ABI_DOUBLE_FLOAT | EF_LARCH_ABI_SOFT_FLOAT) ++ ++/* Returns 0 if everything is ok, != 0 in case of error. */ ++int ++process_elf_file (const char *file_name, const char *lib, int *flag, ++ unsigned int *isa_level, char **soname, void *file_contents, ++ size_t file_length) ++{ ++ ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_contents; ++ Elf64_Ehdr *elf64_header = (Elf64_Ehdr *) elf_header; ++ int ret; ++ long flags; ++ ++ /* LoongArch libraries are always libc.so.6+. */ ++ *flag = FLAG_ELF_LIBC6; ++ ++ 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; ++ ++ /* LoongArch linkers encode the floating point ABI as part of the ELF headers. */ ++ switch (flags & SUPPORTED_ELF_FLAGS) ++ { ++ case EF_LARCH_ABI_SOFT_FLOAT: ++ *flag |= FLAG_LARCH_FLOAT_ABI_SOFT; ++ break; ++ case EF_LARCH_ABI_DOUBLE_FLOAT: ++ *flag |= FLAG_LARCH_FLOAT_ABI_DOUBLE; ++ break; ++ default: ++ return 1; ++ } ++ ++ /* If there are any other ELF flags set then glibc doesn't support this ++ library. */ ++ if (flags & ~SUPPORTED_ELF_FLAGS) ++ return 1; ++ ++ return ret; ++} ++ ++#undef __ELF_NATIVE_CLASS ++#undef process_elf_file ++#define process_elf_file process_elf64_file ++#define __ELF_NATIVE_CLASS 64 ++#include "elf/readelflib.c" +diff --git a/sysdeps/unix/sysv/linux/loongarch/shlib-versions b/sysdeps/unix/sysv/linux/loongarch/shlib-versions +index dc2220b4..5f40e7f5 100644 +--- a/sysdeps/unix/sysv/linux/loongarch/shlib-versions ++++ b/sysdeps/unix/sysv/linux/loongarch/shlib-versions +@@ -2,6 +2,8 @@ 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 ++ld=ld-linux-loongarch-lp64s.so.1 + %else + %error cannot determine ABI + %endif +diff --git a/sysdeps/unix/sysv/linux/loongarch/sysdep.h b/sysdeps/unix/sysv/linux/loongarch/sysdep.h +index e4c8fc29..f4a1d23a 100644 +--- a/sysdeps/unix/sysv/linux/loongarch/sysdep.h ++++ b/sysdeps/unix/sysv/linux/loongarch/sysdep.h +@@ -116,6 +116,7 @@ + /* List of system calls which are supported as vsyscalls. */ + #define HAVE_CLOCK_GETRES64_VSYSCALL "__vdso_clock_getres" + #define HAVE_CLOCK_GETTIME64_VSYSCALL "__vdso_clock_gettime" ++#define HAVE_GETTIMEOFDAY_VSYSCALL "__vdso_gettimeofday" + #define HAVE_GETCPU_VSYSCALL "__vdso_getcpu" + + #define HAVE_CLONE3_WRAPPER 1 +@@ -313,8 +314,64 @@ extern long int __syscall_error (long int neg_errno); + + #endif /* ! __ASSEMBLER__ */ + +-/* Pointer mangling is not supported. */ +-#define PTR_MANGLE(var) (void) (var) +-#define PTR_DEMANGLE(var) (void) (var) ++/* Pointer mangling is supported for LoongArch. */ ++ ++/* Load a got-relative EXPR into G, using T. ++ Note G and T are register names. */ ++#define LD_GLOBAL(G, EXPR) \ ++ la.global G, EXPR; \ ++ REG_L G, G, 0; ++ ++/* Load a pc-relative EXPR into G, using T. ++ Note G and T are register names. */ ++#define LD_PCREL(G, EXPR) \ ++ la.pcrel G, EXPR; \ ++ REG_L G, G, 0; ++ ++#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); \ ++ PTR_MANGLE2 (dst, src, guard); ++#define PTR_DEMANGLE(dst, src, guard) \ ++ LD_PCREL (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) \ ++ xor dst, src, guard; ++#define PTR_DEMANGLE2(dst, src, guard) \ ++ PTR_MANGLE2 (dst, src, guard); ++#else ++extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden; ++#define PTR_MANGLE(var) \ ++ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local) ++#define PTR_DEMANGLE(var) PTR_MANGLE (var) ++#endif ++ ++#else ++ ++#ifdef __ASSEMBLER__ ++#define PTR_MANGLE(dst, src, guard) \ ++ LD_GLOBAL (guard, __pointer_chk_guard); \ ++ PTR_MANGLE2 (dst, src, guard); ++#define PTR_DEMANGLE(dst, src, guard) \ ++ LD_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) \ ++ xor dst, src, guard; ++#define PTR_DEMANGLE2(dst, src, guard) \ ++ PTR_MANGLE2 (dst, src, guard); ++#else ++extern uintptr_t __pointer_chk_guard attribute_relro; ++#define PTR_MANGLE(var) \ ++ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard) ++#define PTR_DEMANGLE(var) PTR_MANGLE (var) ++#endif ++ ++#endif + + #endif /* linux/loongarch/sysdep.h */ +diff --git a/sysdeps/unix/sysv/linux/syscall.c b/sysdeps/unix/sysv/linux/syscall.c +index 7303ba71..8cb0b66b 100644 +--- a/sysdeps/unix/sysv/linux/syscall.c ++++ b/sysdeps/unix/sysv/linux/syscall.c +@@ -33,7 +33,7 @@ syscall (long int number, ...) + long int a5 = va_arg (args, long int); + va_end (args); + +- int r = INTERNAL_SYSCALL_NCS_CALL (number, a0, a1, a2, a3, a4, a5); ++ long int r = INTERNAL_SYSCALL_NCS_CALL (number, a0, a1, a2, a3, a4, a5); + if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (r))) + { + __set_errno (-r); +-- +2.33.0 + diff --git a/glibc.spec b/glibc.spec index 1c0a231..1325b2f 100644 --- a/glibc.spec +++ b/glibc.spec @@ -1,4 +1,4 @@ -%define anolis_release 7 +%define anolis_release 8 %bcond_without testsuite %bcond_without benchtests @@ -175,6 +175,7 @@ Patch0178: 0078-time-Use-64-bit-time-on-tzfile.patch Patch0179: 0079-locale-prevent-maybe-uninitialized-errors-with-Os-BZ.patch Patch0180: 0080-sunrpc-Suppress-GCC-Os-warning-on-user2netname.patch Patch0181: 0081-x86-Fix-Os-build-BZ-29576.patch +Patch0182: 0082-LoongArch-add-new-relocs-and-fix-from-upstream.patch BuildRequires: audit-libs-devel >= 1.1.3 libcap-devel systemtap-sdt-devel BuildRequires: procps-ng util-linux gawk sed >= 3.95 gettext @@ -1107,6 +1108,10 @@ update_gconv_modules_cache () %{_libdir}/libpthread_nonshared.a %changelog +* Tue Aug 8 2023 Peng Fan - 2.36-8 +- LoongArch: backport from upstream. +- upstream commit: eaa5b1cce87d34c945955360b1e519c6994308a1 + * Fri Apr 14 2023 Chunmei Xu - 2.36-7 - optimise spec file