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