1 /* Copyright (C) 1996-2021 Free Software Foundation, Inc. 2 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19 #include <math.h> 20 #include <get-rounding-mode.h> 21 #include <stdint.h> 22 #include <math-barriers.h> 23 #include <libm-alias-double.h> 24 25 # define IREG_SIZE 64 26 27 # ifdef __ILP32__ 28 # define OREG_SIZE 32 29 # else 30 # define OREG_SIZE 64 31 # endif 32 33 # define IREGS "d" 34 35 #if OREG_SIZE == 32 36 # define OREGS "w" 37 #else 38 # define OREGS "x" 39 #endif 40 41 42 long int __lrint(double x)43__lrint (double x) 44 { 45 46 #if IREG_SIZE == 64 && OREG_SIZE == 32 47 long int result; 48 49 if (__builtin_fabs (x) > INT32_MAX) 50 { 51 /* Converting large values to a 32 bit int may cause the frintx/fcvtza 52 sequence to set both FE_INVALID and FE_INEXACT. To avoid this 53 check the rounding mode and do a single instruction with the 54 appropriate rounding mode. */ 55 56 switch (get_rounding_mode ()) 57 { 58 case FE_TONEAREST: 59 asm volatile ("fcvtns" "\t%" OREGS "0, %" IREGS "1" 60 : "=r" (result) : "w" (x)); 61 break; 62 case FE_UPWARD: 63 asm volatile ("fcvtps" "\t%" OREGS "0, %" IREGS "1" 64 : "=r" (result) : "w" (x)); 65 break; 66 case FE_DOWNWARD: 67 asm volatile ("fcvtms" "\t%" OREGS "0, %" IREGS "1" 68 : "=r" (result) : "w" (x)); 69 break; 70 case FE_TOWARDZERO: 71 default: 72 asm volatile ("fcvtzs" "\t%" OREGS "0, %" IREGS "1" 73 : "=r" (result) : "w" (x)); 74 } 75 return result; 76 } 77 #endif 78 79 double r = __builtin_rint (x); 80 81 /* Prevent gcc from calling lrint directly when compiled with 82 -fno-math-errno by inserting a barrier. */ 83 84 math_opt_barrier (r); 85 return r; 86 } 87 88 libm_alias_double (__lrint, lrint) 89