diff options
author | caiyinyu <caiyinyu@loongson.cn> | 2022-07-19 09:22:08 +0800 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2022-07-26 12:35:12 -0300 |
commit | 68d61026d526fff88a7ae64ccf92b3f9da189249 (patch) | |
tree | 5d24601805b547e39ba74b2278b315460d13fed9 | |
parent | 3d87c89815314b0854604a9e9be2990818ca6f6a (diff) | |
download | glibc-68d61026d526fff88a7ae64ccf92b3f9da189249.tar.gz glibc-68d61026d526fff88a7ae64ccf92b3f9da189249.tar.xz glibc-68d61026d526fff88a7ae64ccf92b3f9da189249.zip |
LoongArch: Hard Float Support
22 files changed, 2372 insertions, 0 deletions
diff --git a/sysdeps/loongarch/fpu/fclrexcpt.c b/sysdeps/loongarch/fpu/fclrexcpt.c new file mode 100644 index 0000000000..e9f33a1658 --- /dev/null +++ b/sysdeps/loongarch/fpu/fclrexcpt.c @@ -0,0 +1,46 @@ +/* Clear given exceptions in current floating-point environment. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fenv_libc.h> +#include <fpu_control.h> + +int +feclearexcept (int excepts) +{ + int cw; + + /* Mask out unsupported bits/exceptions. */ + excepts &= FE_ALL_EXCEPT; + + /* Read the complete control word. */ + _FPU_GETCW (cw); + + /* Clear exception flag bits and cause bits. If the cause bit is not + cleared, the next CTC instruction (just below) will re-generate the + exception. */ + + cw &= ~(excepts | (excepts << CAUSE_SHIFT)); + + /* Put the new data in effect. */ + _FPU_SETCW (cw); + + /* Success. */ + return 0; +} +libm_hidden_def (feclearexcept) diff --git a/sysdeps/loongarch/fpu/fedisblxcpt.c b/sysdeps/loongarch/fpu/fedisblxcpt.c new file mode 100644 index 0000000000..add62946fd --- /dev/null +++ b/sysdeps/loongarch/fpu/fedisblxcpt.c @@ -0,0 +1,39 @@ +/* Disable floating-point 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fenv_libc.h> +#include <fpu_control.h> + +int +fedisableexcept (int excepts) +{ + unsigned int new_exc, old_exc; + + /* Get the current control word. */ + _FPU_GETCW (new_exc); + + old_exc = (new_exc & ENABLE_MASK) << ENABLE_SHIFT; + + excepts &= FE_ALL_EXCEPT; + + new_exc &= ~(excepts >> ENABLE_SHIFT); + _FPU_SETCW (new_exc); + + return old_exc; +} diff --git a/sysdeps/loongarch/fpu/feenablxcpt.c b/sysdeps/loongarch/fpu/feenablxcpt.c new file mode 100644 index 0000000000..ed809341f6 --- /dev/null +++ b/sysdeps/loongarch/fpu/feenablxcpt.c @@ -0,0 +1,39 @@ +/* Enable floating-point 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fenv_libc.h> +#include <fpu_control.h> + +int +feenableexcept (int excepts) +{ + unsigned int new_exc, old_exc; + + /* Get the current control word. */ + _FPU_GETCW (new_exc); + + old_exc = (new_exc & ENABLE_MASK) << ENABLE_SHIFT; + + excepts &= FE_ALL_EXCEPT; + + new_exc |= excepts >> ENABLE_SHIFT; + _FPU_SETCW (new_exc); + + return old_exc; +} diff --git a/sysdeps/loongarch/fpu/fegetenv.c b/sysdeps/loongarch/fpu/fegetenv.c new file mode 100644 index 0000000000..5a2a3d34dc --- /dev/null +++ b/sysdeps/loongarch/fpu/fegetenv.c @@ -0,0 +1,31 @@ +/* Store current floating-point environment. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +__fegetenv (fenv_t *envp) +{ + _FPU_GETCW (*envp); + + /* Success. */ + return 0; +} +libm_hidden_def (__fegetenv) weak_alias (__fegetenv, fegetenv) +libm_hidden_weak (fegetenv) diff --git a/sysdeps/loongarch/fpu/fegetexcept.c b/sysdeps/loongarch/fpu/fegetexcept.c new file mode 100644 index 0000000000..ba1c1466f4 --- /dev/null +++ b/sysdeps/loongarch/fpu/fegetexcept.c @@ -0,0 +1,32 @@ +/* Get enabled floating-point 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fenv_libc.h> +#include <fpu_control.h> + +int +fegetexcept (void) +{ + unsigned int exc; + + /* Get the current control word. */ + _FPU_GETCW (exc); + + return (exc & ENABLE_MASK) << ENABLE_SHIFT; +} diff --git a/sysdeps/loongarch/fpu/fegetmode.c b/sysdeps/loongarch/fpu/fegetmode.c new file mode 100644 index 0000000000..e3517e34f6 --- /dev/null +++ b/sysdeps/loongarch/fpu/fegetmode.c @@ -0,0 +1,27 @@ +/* Store current floating-point control modes. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetmode (femode_t *modep) +{ + _FPU_GETCW (*modep); + return 0; +} diff --git a/sysdeps/loongarch/fpu/fegetround.c b/sysdeps/loongarch/fpu/fegetround.c new file mode 100644 index 0000000000..ff6113eb04 --- /dev/null +++ b/sysdeps/loongarch/fpu/fegetround.c @@ -0,0 +1,33 @@ +/* Return current rounding direction. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +__fegetround (void) +{ + int cw; + + /* Get control word. */ + _FPU_GETCW (cw); + + return cw & _FPU_RC_MASK; +} +libm_hidden_def (__fegetround) weak_alias (__fegetround, fegetround) +libm_hidden_weak (fegetround) diff --git a/sysdeps/loongarch/fpu/feholdexcpt.c b/sysdeps/loongarch/fpu/feholdexcpt.c new file mode 100644 index 0000000000..e4f9f6a23b --- /dev/null +++ b/sysdeps/loongarch/fpu/feholdexcpt.c @@ -0,0 +1,40 @@ +/* Store current floating-point environment and clear 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +__feholdexcept (fenv_t *envp) +{ + fpu_control_t cw; + + /* Save the current state. */ + _FPU_GETCW (cw); + envp->__fp_control_register = cw; + + /* Clear all exception enable bits and flags. */ + cw &= ~(_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O | _FPU_MASK_U | _FPU_MASK_I + | FE_ALL_EXCEPT); + _FPU_SETCW (cw); + + return 0; +} + +libm_hidden_def (__feholdexcept) weak_alias (__feholdexcept, feholdexcept) +libm_hidden_weak (feholdexcept) diff --git a/sysdeps/loongarch/fpu/fenv_libc.h b/sysdeps/loongarch/fpu/fenv_libc.h new file mode 100644 index 0000000000..8360ae0377 --- /dev/null +++ b/sysdeps/loongarch/fpu/fenv_libc.h @@ -0,0 +1,30 @@ +/* Internal libc stuff for floating point environment routines. + 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 + <https://www.gnu.org/licenses/>. */ + +#ifndef _FENV_LIBC_H +#define _FENV_LIBC_H 1 + +/* Mask for enabling exceptions and for the CAUSE bits. */ +#define ENABLE_MASK 0x0000001FU +#define CAUSE_MASK 0x1F000000U + +/* Shift for FE_* flags to get up to the ENABLE bits and the CAUSE bits. */ +#define ENABLE_SHIFT 16 +#define CAUSE_SHIFT 8 + +#endif /* _FENV_LIBC_H */ diff --git a/sysdeps/loongarch/fpu/fesetenv.c b/sysdeps/loongarch/fpu/fesetenv.c new file mode 100644 index 0000000000..c10bd11ef9 --- /dev/null +++ b/sysdeps/loongarch/fpu/fesetenv.c @@ -0,0 +1,42 @@ +/* Install given floating-point environment. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +__fesetenv (const fenv_t *envp) +{ + fpu_control_t cw; + + /* Read first current state to flush fpu pipeline. */ + _FPU_GETCW (cw); + + if (envp == FE_DFL_ENV) + _FPU_SETCW (_FPU_DEFAULT); + else if (envp == FE_NOMASK_ENV) + _FPU_SETCW (_FPU_IEEE); + else + _FPU_SETCW (envp->__fp_control_register); + + /* Success. */ + return 0; +} + +libm_hidden_def (__fesetenv) weak_alias (__fesetenv, fesetenv) +libm_hidden_weak (fesetenv) diff --git a/sysdeps/loongarch/fpu/fesetexcept.c b/sysdeps/loongarch/fpu/fesetexcept.c new file mode 100644 index 0000000000..ad76d52d9e --- /dev/null +++ b/sysdeps/loongarch/fpu/fesetexcept.c @@ -0,0 +1,32 @@ +/* Set given exception flags. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexcept (int excepts) +{ + fpu_control_t temp; + + _FPU_GETCW (temp); + temp |= excepts & FE_ALL_EXCEPT; + _FPU_SETCW (temp); + + return 0; +} diff --git a/sysdeps/loongarch/fpu/fesetmode.c b/sysdeps/loongarch/fpu/fesetmode.c new file mode 100644 index 0000000000..fc52fc114b --- /dev/null +++ b/sysdeps/loongarch/fpu/fesetmode.c @@ -0,0 +1,38 @@ +/* Install given floating-point control modes. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +#define FCSR_STATUS 0x1f1f0000 + +int +fesetmode (const femode_t *modep) +{ + fpu_control_t cw; + + _FPU_GETCW (cw); + cw &= FCSR_STATUS; + if (modep == FE_DFL_MODE) + cw |= _FPU_DEFAULT; + else + cw |= *modep & ~FCSR_STATUS; + _FPU_SETCW (cw); + + return 0; +} diff --git a/sysdeps/loongarch/fpu/fesetround.c b/sysdeps/loongarch/fpu/fesetround.c new file mode 100644 index 0000000000..32acac5f96 --- /dev/null +++ b/sysdeps/loongarch/fpu/fesetround.c @@ -0,0 +1,44 @@ +/* Set current rounding direction. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +__fesetround (int round) +{ + fpu_control_t cw; + + if ((round & ~_FPU_RC_MASK) != 0) + /* ROUND is no valid rounding mode. */ + return 1; + + /* Get current state. */ + _FPU_GETCW (cw); + + /* Set rounding bits. */ + cw &= ~_FPU_RC_MASK; + cw |= round; + /* Set new state. */ + _FPU_SETCW (cw); + + return 0; +} + +libm_hidden_def (__fesetround) weak_alias (__fesetround, fesetround) +libm_hidden_weak (fesetround) diff --git a/sysdeps/loongarch/fpu/feupdateenv.c b/sysdeps/loongarch/fpu/feupdateenv.c new file mode 100644 index 0000000000..5ad862a61d --- /dev/null +++ b/sysdeps/loongarch/fpu/feupdateenv.c @@ -0,0 +1,43 @@ +/* Install given floating-point environment and raise 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +__feupdateenv (const fenv_t *envp) +{ + int temp; + + /* Save current exceptions. */ + _FPU_GETCW (temp); + temp &= FE_ALL_EXCEPT; + + /* Install new environment. */ + __fesetenv (envp); + + /* Raise the safed exception. Incidently for us the implementation + defined format of the values in objects of type fexcept_t is the + same as the ones specified using the FE_* constants. */ + __feraiseexcept (temp); + + /* Success. */ + return 0; +} +libm_hidden_def (__feupdateenv) weak_alias (__feupdateenv, feupdateenv) +libm_hidden_weak (feupdateenv) diff --git a/sysdeps/loongarch/fpu/fgetexcptflg.c b/sysdeps/loongarch/fpu/fgetexcptflg.c new file mode 100644 index 0000000000..6130c632c9 --- /dev/null +++ b/sysdeps/loongarch/fpu/fgetexcptflg.c @@ -0,0 +1,38 @@ +/* Store current representation 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + fpu_control_t temp; + + /* Get the current exceptions. */ + _FPU_GETCW (temp); + + /* We only save the relevant bits here. In particular, care has to be + taken with the CAUSE bits, as an inadvertent restore later on could + generate unexpected exceptions. */ + + *flagp = temp & excepts & FE_ALL_EXCEPT; + + /* Success. */ + return 0; +} diff --git a/sysdeps/loongarch/fpu/fraiseexcpt.c b/sysdeps/loongarch/fpu/fraiseexcpt.c new file mode 100644 index 0000000000..c1c612242f --- /dev/null +++ b/sysdeps/loongarch/fpu/fraiseexcpt.c @@ -0,0 +1,80 @@ +/* Raise given 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> +#include <float.h> + +int +__feraiseexcept (int excepts) +{ + const float fp_zero = 0.0f; + const float fp_one = 1.0f; + const float fp_max = FLT_MAX; + const float fp_min = FLT_MIN; + const float fp_1e32 = 1.0e32f; + const float fp_two = 2.0f; + const float fp_three = 3.0f; + + /* Raise exceptions represented by EXPECTS. But we must raise only + one signal at a time. It is important that if the overflow/underflow + exception and the inexact exception are given at the same time, + the overflow/underflow exception follows the inexact exception. */ + + /* First: invalid exception. */ + if (FE_INVALID & excepts) + __asm__ __volatile__("fdiv.s $f0,%0,%0\n\t" + : + : "f"(fp_zero) + : "$f0"); + + /* Next: division by zero. */ + if (FE_DIVBYZERO & excepts) + __asm__ __volatile__("fdiv.s $f0,%0,%1\n\t" + : + : "f"(fp_one), "f"(fp_zero) + : "$f0"); + + /* Next: overflow. */ + if (FE_OVERFLOW & excepts) + /* There's no way to raise overflow without also raising inexact. */ + __asm__ __volatile__("fadd.s $f0,%0,%1\n\t" + : + : "f"(fp_max), "f"(fp_1e32) + : "$f0"); + + /* Next: underflow. */ + if (FE_UNDERFLOW & excepts) + __asm__ __volatile__("fdiv.s $f0,%0,%1\n\t" + : + : "f"(fp_min), "f"(fp_three) + : "$f0"); + + /* Last: inexact. */ + if (FE_INEXACT & excepts) + __asm__ __volatile__("fdiv.s $f0, %0, %1\n\t" + : + : "f"(fp_two), "f"(fp_three) + : "$f0"); + + /* Success. */ + return 0; +} + +libm_hidden_def (__feraiseexcept) weak_alias (__feraiseexcept, feraiseexcept) +libm_hidden_weak (feraiseexcept) diff --git a/sysdeps/loongarch/fpu/fsetexcptflg.c b/sysdeps/loongarch/fpu/fsetexcptflg.c new file mode 100644 index 0000000000..9c135a663d --- /dev/null +++ b/sysdeps/loongarch/fpu/fsetexcptflg.c @@ -0,0 +1,41 @@ +/* Set floating-point environment exception handling. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + fpu_control_t temp; + + /* Get the current exceptions. */ + _FPU_GETCW (temp); + + /* Make sure the flags we want restored are legal. */ + excepts &= FE_ALL_EXCEPT; + + /* Now clear the bits called for, and copy them in from flagp. Note that + we ignore all non-flag bits from *flagp, so they don't matter. */ + temp = (temp & ~excepts) | (*flagp & excepts); + + _FPU_SETCW (temp); + + /* Success. */ + return 0; +} diff --git a/sysdeps/loongarch/fpu/ftestexcept.c b/sysdeps/loongarch/fpu/ftestexcept.c new file mode 100644 index 0000000000..b9563b7ae1 --- /dev/null +++ b/sysdeps/loongarch/fpu/ftestexcept.c @@ -0,0 +1,32 @@ +/* Test exception in current environment. + 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 + <https://www.gnu.org/licenses/>. */ + +#include <fenv.h> +#include <fpu_control.h> + +int +fetestexcept (int excepts) +{ + int cw; + + /* Get current control word. */ + _FPU_GETCW (cw); + + return cw & excepts & FE_ALL_EXCEPT; +} +libm_hidden_def (fetestexcept) diff --git a/sysdeps/loongarch/fpu/math-use-builtins-sqrt.h b/sysdeps/loongarch/fpu/math-use-builtins-sqrt.h new file mode 100644 index 0000000000..e94c915ba6 --- /dev/null +++ b/sysdeps/loongarch/fpu/math-use-builtins-sqrt.h @@ -0,0 +1,4 @@ +#define USE_SQRT_BUILTIN 1 +#define USE_SQRTF_BUILTIN 1 +#define USE_SQRTL_BUILTIN 0 +#define USE_SQRTF128_BUILTIN 0 diff --git a/sysdeps/loongarch/lp64/libm-test-ulps b/sysdeps/loongarch/lp64/libm-test-ulps new file mode 100644 index 0000000000..c711531eec --- /dev/null +++ b/sysdeps/loongarch/lp64/libm-test-ulps @@ -0,0 +1,1412 @@ +# Begin of automatic generation + +# Maximal error of functions: +Function: "acos": +double: 1 +float: 1 +ldouble: 1 + +Function: "acos_downward": +double: 1 +float: 1 +ldouble: 1 + +Function: "acos_towardzero": +double: 1 +float: 1 +ldouble: 1 + +Function: "acos_upward": +double: 1 +float: 1 +ldouble: 1 + +Function: "acosh": +double: 2 +float: 2 +ldouble: 4 + +Function: "acosh_downward": +double: 2 +float: 2 +ldouble: 3 + +Function: "acosh_towardzero": +double: 2 +float: 2 +ldouble: 2 + +Function: "acosh_upward": +double: 2 +float: 2 +ldouble: 3 + +Function: "asin": +double: 1 +float: 1 +ldouble: 1 + +Function: "asin_downward": +double: 1 +float: 1 +ldouble: 2 + +Function: "asin_towardzero": +double: 1 +float: 1 +ldouble: 1 + +Function: "asin_upward": +double: 2 +float: 1 +ldouble: 2 + +Function: "asinh": +double: 2 +float: 2 +ldouble: 4 + +Function: "asinh_downward": +double: 3 +float: 3 +ldouble: 4 + +Function: "asinh_towardzero": +double: 2 +float: 2 +ldouble: 2 + +Function: "asinh_upward": +double: 3 +float: 3 +ldouble: 4 + +Function: "atan": +double: 1 +float: 1 +ldouble: 1 + +Function: "atan2": +float: 2 +ldouble: 2 + +Function: "atan2_downward": +double: 1 +float: 2 +ldouble: 2 + +Function: "atan2_towardzero": +double: 1 +float: 2 +ldouble: 3 + +Function: "atan2_upward": +double: 1 +float: 2 +ldouble: 2 + +Function: "atan_downward": +double: 1 +float: 2 +ldouble: 2 + +Function: "atan_towardzero": +double: 1 +float: 1 +ldouble: 1 + +Function: "atan_upward": +double: 1 +float: 2 +ldouble: 2 + +Function: "atanh": +double: 2 +float: 2 +ldouble: 4 + +Function: "atanh_downward": +double: 3 +float: 3 +ldouble: 4 + +Function: "atanh_towardzero": +double: 2 +float: 2 +ldouble: 2 + +Function: "atanh_upward": +double: 3 +float: 3 +ldouble: 4 + +Function: "cabs": +double: 1 +ldouble: 1 + +Function: "cabs_downward": +double: 1 +ldouble: 1 + +Function: "cabs_towardzero": +double: 1 +ldouble: 1 + +Function: "cabs_upward": +double: 1 +ldouble: 1 + +Function: Real part of "cacos": +double: 1 +float: 2 +ldouble: 2 + +Function: Imaginary part of "cacos": +double: 2 +float: 2 +ldouble: 2 + +Function: Real part of "cacos_downward": +double: 3 +float: 2 +ldouble: 3 + +Function: Imaginary part of "cacos_downward": +double: 5 +float: 3 +ldouble: 6 + +Function: Real part of "cacos_towardzero": +double: 3 +float: 2 +ldouble: 3 + +Function: Imaginary part of "cacos_towardzero": +double: 4 +float: 2 +ldouble: 5 + +Function: Real part of "cacos_upward": +double: 2 +float: 2 +ldouble: 3 + +Function: Imaginary part of "cacos_upward": +double: 5 +float: 7 +ldouble: 7 + +Function: Real part of "cacosh": +double: 2 +float: 2 +ldouble: 2 + +Function: Imaginary part of "cacosh": +double: 1 +float: 2 +ldouble: 2 + +Function: Real part of "cacosh_downward": +double: 4 +float: 2 +ldouble: 5 + +Function: Imaginary part of "cacosh_downward": +double: 3 +float: 3 +ldouble: 4 + +Function: Real part of "cacosh_towardzero": +double: 4 +float: 2 +ldouble: 5 + +Function: Imaginary part of "cacosh_towardzero": +double: 3 +float: 2 +ldouble: 3 + +Function: Real part of "cacosh_upward": +double: 4 +float: 3 +ldouble: 6 + +Function: Imaginary part of "cacosh_upward": +double: 3 +float: 2 +ldouble: 4 + +Function: "carg": +float: 1 +ldouble: 2 + +Function: "carg_downward": +double: 1 +float: 2 +ldouble: 2 + +Function: "carg_towardzero": +double: 1 +float: 2 +ldouble: 3 + +Function: "carg_upward": +double: 1 +float: 2 +ldouble: 2 + +Function: Real part of "casin": +double: 1 +float: 1 +ldouble: 2 + +Function: Imaginary part of "casin": +double: 2 +float: 2 +ldouble: 2 + +Function: Real part of "casin_downward": +double: 3 +float: 2 +ldouble: 3 + +Function: Imaginary part of "casin_downward": +double: 5 +float: 3 +ldouble: 6 + +Function: Real part of "casin_towardzero": +double: 3 +float: 1 +ldouble: 3 + +Function: Imaginary part of "casin_towardzero": +double: 4 +float: 2 +ldouble: 5 + +Function: Real part of "casin_upward": +double: 3 +float: 2 +ldouble: 3 + +Function: Imaginary part of "casin_upward": +double: 5 +float: 7 +ldouble: 7 + +Function: Real part of "casinh": +double: 2 +float: 2 +ldouble: 2 + +Function: Imaginary part of "casinh": +double: 1 +float: 1 +ldouble: 2 + +Function: Real part of "casinh_downward": +double: 5 +float: 3 +ldouble: 6 + +Function: Imaginary part of "casinh_downward": +double: 3 +float: 2 +ldouble: 3 + +Function: Real part of "casinh_towardzero": +double: 4 +float: 2 +ldouble: 5 + +Function: Imaginary part of "casinh_towardzero": +double: 3 +float: 1 +ldouble: 3 + +Function: Real part of "casinh_upward": +double: 5 +float: 7 +ldouble: 7 + +Function: Imaginary part of "casinh_upward": +double: 3 +float: 2 +ldouble: 3 + +Function: Real part of "catan": +double: 1 +float: 1 +ldouble: 1 + +Function: Imaginary part of "catan": +double: 1 +float: 1 +ldouble: 1 + +Function: Real part of "catan_downward": +double: 1 +float: 2 +ldouble: 2 + +Function: Imaginary part of "catan_downward": +double: 2 +float: 2 +ldouble: 2 + +Function: Real part of "catan_towardzero": +double: 1 +float: 2 +ldouble: 2 + +Function: Imaginary part of "catan_towardzero": +double: 2 +float: 2 +ldouble: 2 + +Function: Real part of "catan_upward": +double: 1 +float: 1 +ldouble: 2 + +Function: Imaginary part of "catan_upward": +double: 2 +float: 2 +ldouble: 3 + +Function: Real part of "catanh": +double: 1 +float: 1 +ldouble: 1 + +Function: Imaginary part of "catanh": +double: 1 +float: 1 +ldouble: 1 + +Function: Real part of "catanh_downward": +double: 2 +float: 2 +ldouble: 2 + +Function: Imaginary part of "catanh_downward": +double: 1 +float: 2 +ldouble: 2 + +Function: Real part of "catanh_towardzero": +double: 2 +float: 2 +ldouble: 2 + +Function: Imaginary part of "catanh_towardzero": +double: 1 +float: 2 +ldouble: 2 + +Function: Real part of "catanh_upward": +double: 4 +float: 4 +ldouble: 4 + +Function: Imaginary part of "catanh_upward": +double: 1 +float: 1 +ldouble: 2 + +Function: "cbrt": +double: 4 +float: 1 +ldouble: 1 + +Function: "cbrt_downward": +double: 4 +float: 1 +ldouble: 1 + +Function: "cbrt_towardzero": +double: 3 +float: 1 +ldouble: 1 + +Function: "cbrt_upward": +double: 5 +float: 1 +ldouble: 1 + +Function: Real part of "ccos": +double: 1 +float: 1 +ldouble: 1 + +Function: Imaginary part of "ccos": +double: 1 +float: 1 +ldouble: 1 + +Function: Real part of "ccos_downward": +double: 1 +float: 1 +ldouble: 2 + +Function: Imaginary part of "ccos_downward": +double: 3 +float: 3 +ldouble: 2 + +Function: Real part of "ccos_towardzero": +double: 1 +float: 2 +ldouble: 2 + +Function: Imaginary part of "ccos_towardzero": +double: 3 +float: 3 +ldouble: 2 + +Function: Real part of "ccos_upward": +double: 1 +float: 2 +ldouble: 3 + +Function: Imaginary part of "ccos_upward": +double: 2 +float: 2 +ldouble: 2 + +Function: Real part of "ccosh": +double: 1 +float: 1 +ldouble: 1 + +Function: Imaginary part of "ccosh": +double: 1 +float: 1 +ldouble: 1 + +Function: Real part of "ccosh_downward": +double: 2 +float: 2 +ldouble: 2 + +Function: Imaginary part of "ccosh_downward": +double: 3 +float: 3 +ldouble: 2 + +Function: Real part of "ccosh_towardzero": +double: 2 +float: 3 +ldouble: 2 + +Function: Imaginary part of "ccosh_towardzero": +double: 3 +float: 3 +ldouble: 2 + +Function: Real part of "ccosh_upward": +double: 1 +float: 2 +ldouble: 3 + +Function: Imaginary part of "ccosh_upward": +double: 2 +float: 2 +ldouble: 2 + +Function: Real part of "cexp": +double: 2 +float: 1 +ldouble: 1 + +Function: Imaginary part of "cexp": +double: 1 +float: 2 +ldouble: 1 + +Function: Real part of "cexp_downward": +double: 2 +float: 2 +ldouble: 2 + +Function: Imaginary part of "cexp_downward": +double: 3 +float: 3 +ldouble: 2 + +Function: Real part of "cexp_towardzero": +double: 2 +float: 2 +ldouble: 2 + +Function: Imaginary part of "cexp_towardzero": +double: 3 +float: 3 +ldouble: 2 + +Function: Real part of "cexp_upward": +double: 1 +float: 2 +ldouble: 3 + +Function: Imaginary part of "cexp_upward": +double: 3 +float: 2 +ldouble: 3 + +Function: Real part of "clog": +double: 3 +float: 3 +ldouble: 2 + +Function: Imaginary part of "clog": +double: 1 +float: 1 +ldouble: 1 + +Function: Real part of "clog10": +double: 3 +float: 4 +ldouble: 2 + +Function: Imaginary part of "clog10": +double: 2 +float: 2 +ldouble: 2 + +Function: Real part of "clog10_downward": +double: 5 +float: 5 +ldouble: 3 + +Function: Imaginary part of "clog10_downward": +double: 2 +float: 4 +ldouble: 3 + +Function: Real part of "clog10_towardzero": +double: 5 +float: 6 +ldouble: 4 + +Function: Imaginary part of "clog10_towardzero": +double: 2 +float: 4 +ldouble: 3 + +Function: Real part of "clog10_upward": +double: 6 +float: 5 +ldouble: 4 + +Function: Imaginary part of "clog10_upward": +double: 2 +float: 4 +ldouble: 3 + +Function: Real part of "clog_downward": +double: 4 +float: 3 +ldouble: 3 + +Function: Imaginary part of "clog_downward": +double: 1 +float: 2 +ldouble: 2 + +Function: Real part of "clog_towardzero": +double: 4 +float: 4 +ldouble: 3 + +Function: Imaginary part of "clog_towardzero": +double: 1 +float: 3 +ldouble: 2 + +Function: Real part of "clog_upward": +double: 4 +float: 3 +ldouble: 4 + +Function: Imaginary part of "clog_upward": +double: 1 +float: 2 +ldouble: 2 + +Function: "cos": +double: 1 +float: 1 +ldouble: 2 + +Function: "cos_downward": +double: 1 +float: 1 +ldouble: 3 + +Function: "cos_towardzero": +double: 1 +float: 1 +ldouble: 1 + +Function: "cos_upward": +double: 1 +float: 1 +ldouble: 2 + +Function: "cosh": +double: 2 +float: 2 +ldouble: 2 + +Function: "cosh_downward": +double: 3 +float: 1 +ldouble: 3 + +Function: "cosh_towardzero": +double: 3 +float: 1 +ldouble: 3 + +Function: "cosh_upward": +double: 2 +float: 2 +ldouble: 3 + +Function: Real part of "cpow": +double: 2 +float: 5 +ldouble: 4 + +Function: Imaginary part of "cpow": +float: 2 +ldouble: 1 + +Function: Real part of "cpow_downward": +double: 5 +float: 8 +ldouble: 6 + +Function: Imaginary part of "cpow_downward": +double: 1 +float: 2 +ldouble: 2 + +Function: Real part of "cpow_towardzero": +double: 5 +float: 8 +ldouble: 6 + +Function: Imaginary part of "cpow_towardzero": +double: 1 +float: 2 +ldouble: 2 + +Function: Real part of "cpow_upward": +double: 4 +float: 1 +ldouble: 3 + +Function: Imaginary part of "cpow_upward": +double: 1 +float: 2 +ldouble: 2 + +Function: Real part of "csin": +double: 1 +float: 1 +ldouble: 1 + +Function: Imaginary part of "csin": +ldouble: 1 + +Function: Real part of "csin_downward": +double: 3 +float: 3 +ldouble: 2 + +Function: Imaginary part of "csin_downward": +double: 1 +float: 1 +ldouble: 2 + +Function: Real part of "csin_towardzero": +double: 3 +float: 3 +ldouble: 2 + +Function: Imaginary part of "csin_towardzero": +double: 1 +float: 1 +ldouble: 2 + +Function: Real part of "csin_upward": +double: 2 +float: 2 +ldouble: 2 + +Function: Imaginary part of "csin_upward": +double: 1 +float: 2 +ldouble: 3 + +Function: Real part of "csinh": +float: 1 +ldouble: 1 + +Function: Imaginary part of "csinh": +double: 1 +float: 1 +ldouble: 1 + +Function: Real part of "csinh_downward": +double: 2 +float: 1 +ldouble: 2 + +Function: Imaginary part of "csinh_downward": +double: 3 +float: 3 +ldouble: 2 + +Function: Real part of "csinh_towardzero": +double: 2 +float: 2 +ldouble: 2 + +Function: Imaginary part of "csinh_towardzero": +double: 3 +float: 3 +ldouble: 2 + +Function: Real part of "csinh_upward": +double: 1 +float: 2 +ldouble: 3 + +Function: Imaginary part of "csinh_upward": +double: 2 +float: 2 +ldouble: 2 + +Function: Real part of "csqrt": +double: 2 +float: 2 +ldouble: 2 + +Function: Imaginary part of "csqrt": +double: 2 +float: 2 +ldouble: 2 + +Function: Real part of "csqrt_downward": +double: 5 +float: 4 +ldouble: 4 + +Function: Imaginary part of "csqrt_downward": +double: 4 +float: 3 +ldouble: 3 + +Function: Real part of "csqrt_towardzero": +double: 4 +float: 3 +ldouble: 3 + +Function: Imaginary part of "csqrt_towardzero": +double: 4 +float: 3 +ldouble: 3 + +Function: Real part of "csqrt_upward": +double: 5 +float: 4 +ldouble: 4 + +Function: Imaginary part of "csqrt_upward": +double: 3 +float: 3 +ldouble: 3 + +Function: Real part of "ctan": +double: 2 +float: 1 +ldouble: 3 + +Function: Imaginary part of "ctan": +double: 2 +float: 2 +ldouble: 3 + +Function: Real part of "ctan_downward": +double: 6 +float: 5 +ldouble: 4 + +Function: Imaginary part of "ctan_downward": +double: 2 +float: 2 +ldouble: 5 + +Function: Real part of "ctan_towardzero": +double: 5 +float: 3 +ldouble: 4 + +Function: Imaginary part of "ctan_towardzero": +double: 2 +float: 2 +ldouble: 5 + +Function: Real part of "ctan_upward": +double: 2 +float: 4 +ldouble: 5 + +Function: Imaginary part of "ctan_upward": +double: 2 +float: 2 +ldouble: 5 + +Function: Real part of "ctanh": +double: 2 +float: 2 +ldouble: 3 + +Function: Imaginary part of "ctanh": +double: 2 +float: 2 +ldouble: 3 + +Function: Real part of "ctanh_downward": +double: 4 +float: 2 +ldouble: 5 + +Function: Imaginary part of "ctanh_downward": +double: 6 +float: 5 +ldouble: 4 + +Function: Real part of "ctanh_towardzero": +double: 2 +float: 2 +ldouble: 5 + +Function: Imaginary part of "ctanh_towardzero": +double: 5 +float: 3 +ldouble: 3 + +Function: Real part of "ctanh_upward": +double: 2 +float: 2 +ldouble: 5 + +Function: Imaginary part of "ctanh_upward": +double: 2 +float: 3 +ldouble: 5 + +Function: "erf": +double: 1 +float: 1 +ldouble: 1 + +Function: "erf_downward": +double: 1 +float: 1 +ldouble: 2 + +Function: "erf_towardzero": +double: 1 +float: 1 +ldouble: 1 + +Function: "erf_upward": +double: 1 +float: 1 +ldouble: 2 + +Function: "erfc": +double: 5 +float: 3 +ldouble: 4 + +Function: "erfc_downward": +double: 5 +float: 6 +ldouble: 5 + +Function: "erfc_towardzero": +double: 3 +float: 4 +ldouble: 4 + +Function: "erfc_upward": +double: 5 +float: 6 +ldouble: 5 + +Function: "exp": +double: 1 +float: 1 +ldouble: 1 + +Function: "exp10": +double: 2 +ldouble: 2 + +Function: "exp10_downward": +double: 3 +float: 1 +ldouble: 3 + +Function: "exp10_towardzero": +double: 3 +float: 1 +ldouble: 3 + +Function: "exp10_upward": +double: 2 +float: 1 +ldouble: 3 + +Function: "exp2": +double: 1 +ldouble: 1 + +Function: "exp2_downward": +double: 1 +ldouble: 1 + +Function: "exp2_towardzero": +double: 1 +ldouble: 1 + +Function: "exp2_upward": +double: 1 +float: 1 +ldouble: 2 + +Function: "exp_downward": +double: 1 +float: 1 + +Function: "exp_towardzero": +double: 1 +float: 1 + +Function: "exp_upward": +double: 1 +float: 1 + +Function: "expm1": +double: 1 +float: 1 +ldouble: 2 + +Function: "expm1_downward": +double: 1 +float: 1 +ldouble: 2 + +Function: "expm1_towardzero": +double: 1 +float: 2 +ldouble: 4 + +Function: "expm1_upward": +double: 1 +float: 1 +ldouble: 3 + +Function: "gamma": +double: 4 +float: 7 +ldouble: 5 + +Function: "gamma_downward": +double: 5 +float: 7 +ldouble: 8 + +Function: "gamma_towardzero": +double: 5 +float: 6 +ldouble: 5 + +Function: "gamma_upward": +double: 5 +float: 6 +ldouble: 8 + +Function: "hypot": +double: 1 +ldouble: 1 + +Function: "hypot_downward": +double: 1 +ldouble: 1 + +Function: "hypot_towardzero": +double: 1 +ldouble: 1 + +Function: "hypot_upward": +double: 1 +ldouble: 1 + +Function: "j0": +double: 3 +float: 9 +ldouble: 2 + +Function: "j0_downward": +double: 6 +float: 9 +ldouble: 9 + +Function: "j0_towardzero": +double: 7 +float: 9 +ldouble: 9 + +Function: "j0_upward": +double: 9 +float: 9 +ldouble: 7 + +Function: "j1": +double: 4 +float: 9 +ldouble: 4 + +Function: "j1_downward": +double: 5 +float: 8 +ldouble: 4 + +Function: "j1_towardzero": +double: 4 +float: 8 +ldouble: 4 + +Function: "j1_upward": +double: 9 +float: 9 +ldouble: 3 + +Function: "jn": +double: 4 +float: 4 +ldouble: 7 + +Function: "jn_downward": +double: 5 +float: 5 +ldouble: 8 + +Function: "jn_towardzero": +double: 5 +float: 5 +ldouble: 8 + +Function: "jn_upward": +double: 5 +float: 4 +ldouble: 7 + +Function: "lgamma": +double: 4 +float: 7 +ldouble: 5 + +Function: "lgamma_downward": +double: 5 +float: 7 +ldouble: 8 + +Function: "lgamma_towardzero": +double: 5 +float: 6 +ldouble: 5 + +Function: "lgamma_upward": +double: 5 +float: 6 +ldouble: 8 + +Function: "log": +double: 1 +ldouble: 1 + +Function: "log10": +double: 2 +float: 2 +ldouble: 2 + +Function: "log10_downward": +double: 2 +float: 3 +ldouble: 1 + +Function: "log10_towardzero": +double: 2 +float: 1 +ldouble: 1 + +Function: "log10_upward": +double: 2 +float: 2 +ldouble: 1 + +Function: "log1p": +double: 1 +float: 1 +ldouble: 3 + +Function: "log1p_downward": +double: 2 +float: 2 +ldouble: 3 + +Function: "log1p_towardzero": +double: 2 +float: 2 +ldouble: 3 + +Function: "log1p_upward": +double: 2 +float: 2 +ldouble: 2 + +Function: "log2": +double: 1 +float: 1 +ldouble: 3 + +Function: "log2_downward": +double: 3 +ldouble: 3 + +Function: "log2_towardzero": +double: 2 +ldouble: 1 + +Function: "log2_upward": +double: 3 +ldouble: 1 + +Function: "log_downward": +ldouble: 1 + +Function: "log_towardzero": +ldouble: 2 + +Function: "log_upward": +double: 1 +ldouble: 2 + +Function: "pow": +double: 1 +ldouble: 2 + +Function: "pow_downward": +double: 1 +float: 1 +ldouble: 2 + +Function: "pow_towardzero": +double: 1 +float: 1 +ldouble: 2 + +Function: "pow_upward": +double: 1 +float: 1 +ldouble: 2 + +Function: "sin": +double: 1 +float: 1 +ldouble: 2 + +Function: "sin_downward": +double: 1 +float: 1 +ldouble: 3 + +Function: "sin_towardzero": +double: 1 +float: 1 +ldouble: 2 + +Function: "sin_upward": +double: 1 +float: 1 +ldouble: 3 + +Function: "sincos": +double: 1 +ldouble: 1 + +Function: "sincos_downward": +double: 1 +float: 1 +ldouble: 3 + +Function: "sincos_towardzero": +double: 1 +float: 1 +ldouble: 2 + +Function: "sincos_upward": +double: 1 +float: 1 +ldouble: 3 + +Function: "sinh": +double: 2 +float: 2 +ldouble: 2 + +Function: "sinh_downward": +double: 3 +float: 3 +ldouble: 3 + +Function: "sinh_towardzero": +double: 3 +float: 2 +ldouble: 3 + +Function: "sinh_upward": +double: 3 +float: 3 +ldouble: 4 + +Function: "tan": +double: 1 +float: 1 +ldouble: 1 + +Function: "tan_downward": +double: 1 +float: 2 +ldouble: 1 + +Function: "tan_towardzero": +double: 1 +float: 1 +ldouble: 1 + +Function: "tan_upward": +double: 1 +float: 1 +ldouble: 1 + +Function: "tanh": +double: 2 +float: 2 +ldouble: 2 + +Function: "tanh_downward": +double: 3 +float: 3 +ldouble: 4 + +Function: "tanh_towardzero": +double: 2 +float: 2 +ldouble: 3 + +Function: "tanh_upward": +double: 3 +float: 3 +ldouble: 3 + +Function: "tgamma": +double: 9 +float: 8 +ldouble: 4 + +Function: "tgamma_downward": +double: 9 +float: 7 +ldouble: 5 + +Function: "tgamma_towardzero": +double: 9 +float: 7 +ldouble: 5 + +Function: "tgamma_upward": +double: 9 +float: 8 +ldouble: 4 + +Function: "y0": +double: 3 +float: 9 +ldouble: 3 + +Function: "y0_downward": +double: 3 +float: 9 +ldouble: 7 + +Function: "y0_towardzero": +double: 4 +float: 9 +ldouble: 3 + +Function: "y0_upward": +double: 3 +float: 9 +ldouble: 4 + +Function: "y1": +double: 3 +float: 9 +ldouble: 5 + +Function: "y1_downward": +double: 6 +float: 9 +ldouble: 5 + +Function: "y1_towardzero": +double: 3 +float: 9 +ldouble: 2 + +Function: "y1_upward": +double: 7 +float: 9 +ldouble: 5 + +Function: "yn": +double: 3 +float: 3 +ldouble: 5 + +Function: "yn_downward": +double: 3 +float: 4 +ldouble: 5 + +Function: "yn_towardzero": +double: 3 +float: 3 +ldouble: 5 + +Function: "yn_upward": +double: 4 +float: 5 +ldouble: 5 + +# end of automatic generation diff --git a/sysdeps/loongarch/lp64/libm-test-ulps-name b/sysdeps/loongarch/lp64/libm-test-ulps-name new file mode 100644 index 0000000000..ce02281eab --- /dev/null +++ b/sysdeps/loongarch/lp64/libm-test-ulps-name @@ -0,0 +1 @@ +LoongArch 64-bit diff --git a/sysdeps/loongarch/math_private.h b/sysdeps/loongarch/math_private.h new file mode 100644 index 0000000000..cdf26a78dd --- /dev/null +++ b/sysdeps/loongarch/math_private.h @@ -0,0 +1,248 @@ +/* Internal math stuff. + 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 + <https://www.gnu.org/licenses/>. */ + +#ifndef LOONGARCH_MATH_PRIVATE_H +#define LOONGARCH_MATH_PRIVATE_H 1 + +/* Inline functions to speed up the math library implementation. The + default versions of these routines are in generic/math_private.h + and call fesetround, feholdexcept, etc. These routines use inlined + code instead. */ + +#ifdef __loongarch_hard_float + +#include <fenv.h> +#include <fenv_libc.h> +#include <fpu_control.h> + +#define _FPU_MASK_ALL \ + (_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O | _FPU_MASK_U | _FPU_MASK_I \ + | FE_ALL_EXCEPT) + +static __always_inline void +libc_feholdexcept_loongarch (fenv_t *envp) +{ + fpu_control_t cw; + + /* Save the current state. */ + _FPU_GETCW (cw); + envp->__fp_control_register = cw; + + /* Clear all exception enable bits and flags. */ + cw &= ~(_FPU_MASK_ALL); + _FPU_SETCW (cw); +} +#define libc_feholdexcept libc_feholdexcept_loongarch +#define libc_feholdexceptf libc_feholdexcept_loongarch +#define libc_feholdexceptl libc_feholdexcept_loongarch + +static __always_inline void +libc_fesetround_loongarch (int round) +{ + fpu_control_t cw; + + /* Get current state. */ + _FPU_GETCW (cw); + + /* Set rounding bits. */ + cw &= ~_FPU_RC_MASK; + cw |= round; + + /* Set new state. */ + _FPU_SETCW (cw); +} +#define libc_fesetround libc_fesetround_loongarch +#define libc_fesetroundf libc_fesetround_loongarch +#define libc_fesetroundl libc_fesetround_loongarch + +static __always_inline void +libc_feholdexcept_setround_loongarch (fenv_t *envp, int round) +{ + fpu_control_t cw; + + /* Save the current state. */ + _FPU_GETCW (cw); + envp->__fp_control_register = cw; + + /* Clear all exception enable bits and flags. */ + cw &= ~(_FPU_MASK_ALL); + + /* Set rounding bits. */ + cw &= ~_FPU_RC_MASK; + cw |= round; + + /* Set new state. */ + _FPU_SETCW (cw); +} +#define libc_feholdexcept_setround libc_feholdexcept_setround_loongarch +#define libc_feholdexcept_setroundf libc_feholdexcept_setround_loongarch +#define libc_feholdexcept_setroundl libc_feholdexcept_setround_loongarch + +#define libc_feholdsetround libc_feholdexcept_setround_loongarch +#define libc_feholdsetroundf libc_feholdexcept_setround_loongarch +#define libc_feholdsetroundl libc_feholdexcept_setround_loongarch + +static __always_inline void +libc_fesetenv_loongarch (fenv_t *envp) +{ + fpu_control_t cw __attribute__ ((unused)); + + /* Read current state to flush fpu pipeline. */ + _FPU_GETCW (cw); + + _FPU_SETCW (envp->__fp_control_register); +} +#define libc_fesetenv libc_fesetenv_loongarch +#define libc_fesetenvf libc_fesetenv_loongarch +#define libc_fesetenvl libc_fesetenv_loongarch + +static __always_inline int +libc_feupdateenv_test_loongarch (fenv_t *envp, int excepts) +{ + /* int ret = fetestexcept (excepts); feupdateenv (envp); return ret; */ + int cw, temp; + + /* Get current control word. */ + _FPU_GETCW (cw); + + /* Set flag bits (which are accumulative), and *also* set the + cause bits. The setting of the cause bits is what actually causes + the hardware to generate the exception, if the corresponding enable + bit is set as well. */ + temp = cw & FE_ALL_EXCEPT; + temp |= envp->__fp_control_register | (temp << CAUSE_SHIFT); + + /* Set new state. */ + _FPU_SETCW (temp); + + return cw & excepts & FE_ALL_EXCEPT; +} +#define libc_feupdateenv_test libc_feupdateenv_test_loongarch +#define libc_feupdateenv_testf libc_feupdateenv_test_loongarch +#define libc_feupdateenv_testl libc_feupdateenv_test_loongarch + +static __always_inline void +libc_feupdateenv_loongarch (fenv_t *envp) +{ + libc_feupdateenv_test_loongarch (envp, 0); +} +#define libc_feupdateenv libc_feupdateenv_loongarch +#define libc_feupdateenvf libc_feupdateenv_loongarch +#define libc_feupdateenvl libc_feupdateenv_loongarch + +#define libc_feresetround libc_feupdateenv_loongarch +#define libc_feresetroundf libc_feupdateenv_loongarch +#define libc_feresetroundl libc_feupdateenv_loongarch + +static __always_inline int +libc_fetestexcept_loongarch (int excepts) +{ + int cw; + + /* Get current control word. */ + _FPU_GETCW (cw); + + return cw & excepts & FE_ALL_EXCEPT; +} +#define libc_fetestexcept libc_fetestexcept_loongarch +#define libc_fetestexceptf libc_fetestexcept_loongarch +#define libc_fetestexceptl libc_fetestexcept_loongarch + +/* Enable support for rounding mode context. */ +#define HAVE_RM_CTX 1 + +static __always_inline void +libc_feholdexcept_setround_loongarch_ctx (struct rm_ctx *ctx, int round) +{ + fpu_control_t old, new; + + /* Save the current state. */ + _FPU_GETCW (old); + ctx->env.__fp_control_register = old; + + /* Clear all exception enable bits and flags. */ + new = old & ~(_FPU_MASK_ALL); + + /* Set rounding bits. */ + new = (new & ~_FPU_RC_MASK) | round; + + if (__glibc_unlikely (new != old)) + { + _FPU_SETCW (new); + ctx->updated_status = true; + } + else + ctx->updated_status = false; +} +#define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_loongarch_ctx +#define libc_feholdexcept_setroundf_ctx \ + libc_feholdexcept_setround_loongarch_ctx +#define libc_feholdexcept_setroundl_ctx \ + libc_feholdexcept_setround_loongarch_ctx + +static __always_inline void +libc_fesetenv_loongarch_ctx (struct rm_ctx *ctx) +{ + libc_fesetenv_loongarch (&ctx->env); +} +#define libc_fesetenv_ctx libc_fesetenv_loongarch_ctx +#define libc_fesetenvf_ctx libc_fesetenv_loongarch_ctx +#define libc_fesetenvl_ctx libc_fesetenv_loongarch_ctx + +static __always_inline void +libc_feupdateenv_loongarch_ctx (struct rm_ctx *ctx) +{ + if (__glibc_unlikely (ctx->updated_status)) + libc_feupdateenv_test_loongarch (&ctx->env, 0); +} +#define libc_feupdateenv_ctx libc_feupdateenv_loongarch_ctx +#define libc_feupdateenvf_ctx libc_feupdateenv_loongarch_ctx +#define libc_feupdateenvl_ctx libc_feupdateenv_loongarch_ctx +#define libc_feresetround_ctx libc_feupdateenv_loongarch_ctx +#define libc_feresetroundf_ctx libc_feupdateenv_loongarch_ctx +#define libc_feresetroundl_ctx libc_feupdateenv_loongarch_ctx + +static __always_inline void +libc_feholdsetround_loongarch_ctx (struct rm_ctx *ctx, int round) +{ + fpu_control_t old, new; + + /* Save the current state. */ + _FPU_GETCW (old); + ctx->env.__fp_control_register = old; + + /* Set rounding bits. */ + new = (old & ~_FPU_RC_MASK) | round; + + if (__glibc_unlikely (new != old)) + { + _FPU_SETCW (new); + ctx->updated_status = true; + } + else + ctx->updated_status = false; +} +#define libc_feholdsetround_ctx libc_feholdsetround_loongarch_ctx +#define libc_feholdsetroundf_ctx libc_feholdsetround_loongarch_ctx +#define libc_feholdsetroundl_ctx libc_feholdsetround_loongarch_ctx + +#endif + +#include_next <math_private.h> + +#endif |