diff options
Diffstat (limited to 'sysdeps/aarch64/fpu/s_lrint.c')
-rw-r--r-- | sysdeps/aarch64/fpu/s_lrint.c | 82 |
1 files changed, 59 insertions, 23 deletions
diff --git a/sysdeps/aarch64/fpu/s_lrint.c b/sysdeps/aarch64/fpu/s_lrint.c index e51de0fc2d..d6ef066e45 100644 --- a/sysdeps/aarch64/fpu/s_lrint.c +++ b/sysdeps/aarch64/fpu/s_lrint.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2016 Free Software Foundation, Inc. +/* Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -17,37 +17,73 @@ <http://www.gnu.org/licenses/>. */ #include <math.h> +#include <get-rounding-mode.h> +#include <stdint.h> +#include <math-barriers.h> +#include <math_private.h> +#include <libm-alias-double.h> -#ifndef FUNC -# define FUNC lrint -#endif +# define IREG_SIZE 64 + +# ifdef __ILP32__ +# define OREG_SIZE 32 +# else +# define OREG_SIZE 64 +# endif -#ifndef ITYPE -# define ITYPE double # define IREGS "d" + +#if OREG_SIZE == 32 +# define OREGS "w" #else -# ifndef IREGS -# error IREGS not defined -# endif +# define OREGS "x" #endif -#ifndef OTYPE -# define OTYPE long int + +long int +__lrint (double x) +{ + +#if IREG_SIZE == 64 && OREG_SIZE == 32 + long int result; + + if (__builtin_fabs (x) > INT32_MAX) + { + /* Converting large values to a 32 bit int may cause the frintx/fcvtza + sequence to set both FE_INVALID and FE_INEXACT. To avoid this + check the rounding mode and do a single instruction with the + appropriate rounding mode. */ + + switch (get_rounding_mode ()) + { + case FE_TONEAREST: + asm volatile ("fcvtns" "\t%" OREGS "0, %" IREGS "1" + : "=r" (result) : "w" (x)); + break; + case FE_UPWARD: + asm volatile ("fcvtps" "\t%" OREGS "0, %" IREGS "1" + : "=r" (result) : "w" (x)); + break; + case FE_DOWNWARD: + asm volatile ("fcvtms" "\t%" OREGS "0, %" IREGS "1" + : "=r" (result) : "w" (x)); + break; + case FE_TOWARDZERO: + default: + asm volatile ("fcvtzs" "\t%" OREGS "0, %" IREGS "1" + : "=r" (result) : "w" (x)); + } + return result; + } #endif -#define OREGS "x" + double r = __builtin_rint (x); -#define __CONCATX(a,b) __CONCAT(a,b) + /* Prevent gcc from calling lrint directly when compiled with + -fno-math-errno by inserting a barrier. */ -OTYPE -__CONCATX(__,FUNC) (ITYPE x) -{ - OTYPE result; - ITYPE temp; - asm ( "frintx" "\t%" IREGS "1, %" IREGS "2\n\t" - "fcvtzs" "\t%" OREGS "0, %" IREGS "1" - : "=r" (result), "=w" (temp) : "w" (x) ); - return result; + math_opt_barrier (r); + return r; } -weak_alias (__CONCATX(__,FUNC), FUNC) +libm_alias_double (__lrint, lrint) |