From 394782ac1a2b67e922be4752c223c2d188754e0d Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Sat, 4 Jul 2015 20:10:39 -0700 Subject: [PATCH] Fix some glibc FP routines for non-F Some glibc floating point routines use inline assembly. This changes them to use regular C code to do this when compiled without hardware floatint-point support. The change just uses regular C to perform these operations when compiled on ABIs without hardware floating point. --- glibc/sysdeps/riscv/fpu/s_fdim.c | 5 +++++ glibc/sysdeps/riscv/fpu/s_fdimf.c | 5 +++++ glibc/sysdeps/riscv/fpu/s_fmax.c | 8 ++++++++ glibc/sysdeps/riscv/fpu/s_fmaxf.c | 8 ++++++++ glibc/sysdeps/riscv/fpu/s_fmin.c | 8 ++++++++ glibc/sysdeps/riscv/fpu/s_fminf.c | 8 ++++++++ glibc/sysdeps/riscv/fpu_control.h | 8 ++++++-- 7 files changed, 48 insertions(+), 2 deletions(-) diff --git a/glibc/sysdeps/riscv/fpu/s_fdim.c b/glibc/sysdeps/riscv/fpu/s_fdim.c index 9835f591..96c61997 100644 --- a/glibc/sysdeps/riscv/fpu/s_fdim.c +++ b/glibc/sysdeps/riscv/fpu/s_fdim.c @@ -9,8 +9,13 @@ double __fdim (double x, double y) if (x <= y) return 0.0; +#ifdef __riscv_soft_float + if (isinf(diff)) + errno = ERANGE; +#else if (__builtin_expect(_FCLASS(diff) & _FCLASS_INF, 0)) errno = ERANGE; +#endif return diff; } diff --git a/glibc/sysdeps/riscv/fpu/s_fdimf.c b/glibc/sysdeps/riscv/fpu/s_fdimf.c index 480136cc..893132ad 100644 --- a/glibc/sysdeps/riscv/fpu/s_fdimf.c +++ b/glibc/sysdeps/riscv/fpu/s_fdimf.c @@ -9,8 +9,13 @@ float __fdimf (float x, float y) if (x <= y) return 0.0f; +#ifdef __riscv_soft_float + if (isinf(diff)) + errno = ERANGE; +#else if (__builtin_expect(_FCLASS(diff) & _FCLASS_INF, 0)) errno = ERANGE; +#endif return diff; } diff --git a/glibc/sysdeps/riscv/fpu/s_fmax.c b/glibc/sysdeps/riscv/fpu/s_fmax.c index 8d2e662f..e133c675 100644 --- a/glibc/sysdeps/riscv/fpu/s_fmax.c +++ b/glibc/sysdeps/riscv/fpu/s_fmax.c @@ -2,8 +2,16 @@ double __fmax (double x, double y) { +#ifdef __riscv_soft_float + if (isnan(x)) + return y; + if (isnan(y)) + return x; + return (x > y) ? x : y; +#else double res; asm ("fmax.d %0, %1, %2" : "=f"(res) : "f"(x), "f"(y)); return res; +#endif } weak_alias (__fmax, fmax) diff --git a/glibc/sysdeps/riscv/fpu/s_fmaxf.c b/glibc/sysdeps/riscv/fpu/s_fmaxf.c index aa621729..6ec578c1 100644 --- a/glibc/sysdeps/riscv/fpu/s_fmaxf.c +++ b/glibc/sysdeps/riscv/fpu/s_fmaxf.c @@ -2,8 +2,16 @@ float __fmaxf (float x, float y) { +#ifdef __riscv_soft_float + if (isnan(x)) + return y; + if (isnan(y)) + return x; + return (x > y) ? x : y; +#else float res; asm ("fmax.s %0, %1, %2" : "=f"(res) : "f"(x), "f"(y)); return res; +#endif } weak_alias (__fmaxf, fmaxf) diff --git a/glibc/sysdeps/riscv/fpu/s_fmin.c b/glibc/sysdeps/riscv/fpu/s_fmin.c index e4e37df9..8330620d 100644 --- a/glibc/sysdeps/riscv/fpu/s_fmin.c +++ b/glibc/sysdeps/riscv/fpu/s_fmin.c @@ -2,8 +2,16 @@ double __fmin (double x, double y) { +#ifdef __riscv_soft_float + if (isnan(x)) + return y; + if (isnan(y)) + return x; + return (x < y) ? x : y; +#else double res; asm ("fmin.d %0, %1, %2" : "=f"(res) : "f"(x), "f"(y)); return res; +#endif } weak_alias (__fmin, fmin) diff --git a/glibc/sysdeps/riscv/fpu/s_fminf.c b/glibc/sysdeps/riscv/fpu/s_fminf.c index 5d25bc28..00dcb6c5 100644 --- a/glibc/sysdeps/riscv/fpu/s_fminf.c +++ b/glibc/sysdeps/riscv/fpu/s_fminf.c @@ -2,8 +2,16 @@ float __fminf (float x, float y) { +#ifdef __riscv_soft_float + if (isnan(x)) + return y; + if (isnan(y)) + return x; + return (x < y) ? x : y; +#else float res; asm ("fmin.s %0, %1, %2" : "=f"(res) : "f"(x), "f"(y)); return res; +#endif } weak_alias (__fminf, fminf) diff --git a/glibc/sysdeps/riscv/fpu_control.h b/glibc/sysdeps/riscv/fpu_control.h index c47d03b3..cd52ff99 100644 --- a/glibc/sysdeps/riscv/fpu_control.h +++ b/glibc/sysdeps/riscv/fpu_control.h @@ -30,10 +30,14 @@ #define _FPU_DEFAULT 0x00000000 typedef unsigned int fpu_control_t; #define _FPU_GETCW(cw) (cw) = 0 +#define _FPU_GETROUND(cw) (cw) = 0 +#define _FPU_GETFLAGS(cw) (cw) = 0 #define _FPU_SETCW(cw) do { } while (0) +#define _FPU_SETROUND(cw) do { } while (0) +#define _FPU_SETFLAGS(cw) do { } while (0) extern fpu_control_t __fpu_control; -#else /* __mips_soft_float */ +#else /* __riscv_soft_float */ /* rounding control */ #define _FPU_RC_NEAREST 0x0 @@ -87,6 +91,6 @@ extern fpu_control_t __fpu_control; #define _FCLASS_INF (_FCLASS_MINF | _FCLASS_PINF) #define _FCLASS_NAN (_FCLASS_SNAN | _FCLASS_QNAN) -#endif /* __mips_soft_float */ +#endif /* __riscv_soft_float */ #endif /* fpu_control.h */