]>
Commit | Line | Data |
---|---|---|
bfff8b1b | 1 | /* Copyright (C) 1996-2017 Free Software Foundation, Inc. |
a6d9783f MS |
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 | <http://www.gnu.org/licenses/>. */ | |
18 | ||
19 | #include <math.h> | |
d9ff799a SE |
20 | #include <get-rounding-mode.h> |
21 | #include <stdint.h> | |
a6d9783f MS |
22 | |
23 | #ifndef FUNC | |
5c5bd24e | 24 | # define FUNC lrint |
a6d9783f MS |
25 | #endif |
26 | ||
27 | #ifndef ITYPE | |
5c5bd24e | 28 | # define ITYPE double |
d9ff799a | 29 | # define IREG_SIZE 64 |
a6d9783f | 30 | #else |
d9ff799a SE |
31 | # ifndef IREG_SIZE |
32 | # error IREG_SIZE not defined | |
5c5bd24e | 33 | # endif |
a6d9783f MS |
34 | #endif |
35 | ||
36 | #ifndef OTYPE | |
5c5bd24e | 37 | # define OTYPE long int |
d9ff799a SE |
38 | # ifdef __ILP32__ |
39 | # define OREG_SIZE 32 | |
40 | # else | |
41 | # define OREG_SIZE 64 | |
42 | # endif | |
43 | #else | |
44 | # ifndef OREG_SIZE | |
45 | # error OREG_SIZE not defined | |
46 | # endif | |
a6d9783f MS |
47 | #endif |
48 | ||
d9ff799a SE |
49 | #if IREG_SIZE == 32 |
50 | # define IREGS "s" | |
51 | #else | |
52 | # define IREGS "d" | |
53 | #endif | |
54 | ||
55 | #if OREG_SIZE == 32 | |
56 | # define OREGS "w" | |
57 | #else | |
58 | # define OREGS "x" | |
59 | #endif | |
a6d9783f MS |
60 | |
61 | #define __CONCATX(a,b) __CONCAT(a,b) | |
62 | ||
63 | OTYPE | |
5e543752 | 64 | __CONCATX(__,FUNC) (ITYPE x) |
a6d9783f MS |
65 | { |
66 | OTYPE result; | |
67 | ITYPE temp; | |
d9ff799a SE |
68 | |
69 | #if IREG_SIZE == 64 && OREG_SIZE == 32 | |
70 | if (__builtin_fabs (x) > INT32_MAX) | |
71 | { | |
72 | /* Converting large values to a 32 bit int may cause the frintx/fcvtza | |
73 | sequence to set both FE_INVALID and FE_INEXACT. To avoid this | |
74 | check the rounding mode and do a single instruction with the | |
75 | appropriate rounding mode. */ | |
76 | ||
77 | switch (get_rounding_mode ()) | |
78 | { | |
79 | case FE_TONEAREST: | |
80 | asm volatile ("fcvtns" "\t%" OREGS "0, %" IREGS "1" | |
81 | : "=r" (result) : "w" (x)); | |
82 | break; | |
83 | case FE_UPWARD: | |
84 | asm volatile ("fcvtps" "\t%" OREGS "0, %" IREGS "1" | |
85 | : "=r" (result) : "w" (x)); | |
86 | break; | |
87 | case FE_DOWNWARD: | |
88 | asm volatile ("fcvtms" "\t%" OREGS "0, %" IREGS "1" | |
89 | : "=r" (result) : "w" (x)); | |
90 | break; | |
91 | case FE_TOWARDZERO: | |
92 | default: | |
93 | asm volatile ("fcvtzs" "\t%" OREGS "0, %" IREGS "1" | |
94 | : "=r" (result) : "w" (x)); | |
95 | } | |
96 | return result; | |
97 | } | |
98 | #endif | |
a6d9783f MS |
99 | asm ( "frintx" "\t%" IREGS "1, %" IREGS "2\n\t" |
100 | "fcvtzs" "\t%" OREGS "0, %" IREGS "1" | |
101 | : "=r" (result), "=w" (temp) : "w" (x) ); | |
102 | return result; | |
103 | } | |
104 | ||
3bae7c5d | 105 | weak_alias (__CONCATX(__,FUNC), FUNC) |