]>
Commit | Line | Data |
---|---|---|
8da2915d UD |
1 | .file "rint.s" |
2 | ||
a334319f | 3 | // Copyright (C) 2000, 2001, Intel Corporation |
8da2915d | 4 | // All rights reserved. |
a334319f UD |
5 | // |
6 | // Contributed 2/2/2000 by John Harrison, Ted Kubaska, Bob Norin, Shane Story, | |
7 | // and Ping Tak Peter Tang of the Computational Software Lab, Intel Corporation. | |
aeb25823 AJ |
8 | // |
9 | // Redistribution and use in source and binary forms, with or without | |
10 | // modification, are permitted provided that the following conditions are | |
11 | // met: | |
12 | // | |
13 | // * Redistributions of source code must retain the above copyright | |
14 | // notice, this list of conditions and the following disclaimer. | |
15 | // | |
16 | // * Redistributions in binary form must reproduce the above copyright | |
17 | // notice, this list of conditions and the following disclaimer in the | |
18 | // documentation and/or other materials provided with the distribution. | |
19 | // | |
20 | // * The name of Intel Corporation may not be used to endorse or promote | |
21 | // products derived from this software without specific prior written | |
22 | // permission. | |
a334319f UD |
23 | // |
24 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
25 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
8da2915d | 26 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
a334319f | 27 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS |
8da2915d | 28 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
a334319f UD |
29 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
30 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
31 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
8da2915d | 32 | // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING |
a334319f UD |
33 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
34 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
35 | // | |
8da2915d | 36 | // Intel Corporation is the author of this code, and requests that all |
a334319f UD |
37 | // problem reports or change requests be submitted to it directly at |
38 | // http://developer.intel.com/opensource. | |
8da2915d UD |
39 | // |
40 | // History | |
41 | //============================================================== | |
a334319f UD |
42 | // 2/02/00: Initial version |
43 | // 2/08/01 Corrected behavior for all rounding modes. | |
44 | // | |
8da2915d UD |
45 | // API |
46 | //============================================================== | |
47 | // double rint(double x) | |
48 | ||
a334319f UD |
49 | #include "libm_support.h" |
50 | ||
51 | // | |
52 | // general registers used: | |
53 | // | |
54 | rint_GR_FFFF = r14 | |
55 | rint_GR_signexp = r15 | |
56 | rint_GR_exponent = r16 | |
57 | rint_GR_17ones = r17 | |
58 | rint_GR_10033 = r18 | |
59 | rint_GR_fpsr = r19 | |
60 | rint_GR_rcs0 = r20 | |
61 | rint_GR_rcs0_mask = r21 | |
8da2915d UD |
62 | |
63 | ||
a334319f UD |
64 | // predicate registers used: |
65 | // p6-11 | |
8da2915d | 66 | |
a334319f | 67 | // floating-point registers used: |
8da2915d | 68 | |
a334319f UD |
69 | RINT_NORM_f8 = f9 |
70 | RINT_FFFF = f10 | |
71 | RINT_INEXACT = f11 | |
72 | RINT_FLOAT_INT_f8 = f12 | |
73 | RINT_INT_f8 = f13 | |
8da2915d UD |
74 | |
75 | // Overview of operation | |
76 | //============================================================== | |
a334319f | 77 | |
8da2915d | 78 | // double rint(double x) |
a334319f UD |
79 | // Return an integer value (represented as a double) that is x rounded to integer in current |
80 | // rounding mode | |
8da2915d | 81 | // Inexact is set if x != rint(x) |
a334319f UD |
82 | // ******************************************************************************* |
83 | ||
84 | // Set denormal flag for denormal input and | |
85 | // and take denormal fault if necessary. | |
86 | ||
87 | // Is the input an integer value already? | |
8da2915d UD |
88 | |
89 | // double_extended | |
a334319f | 90 | // if the exponent is >= 1003e => 3F(true) = 63(decimal) |
8da2915d UD |
91 | // we have a significand of 64 bits 1.63-bits. |
92 | // If we multiply by 2^63, we no longer have a fractional part | |
93 | // So input is an integer value already. | |
94 | ||
95 | // double | |
96 | // if the exponent is >= 10033 => 34(true) = 52(decimal) | |
97 | // 34 + 3ff = 433 | |
98 | // we have a significand of 53 bits 1.52-bits. (implicit 1) | |
99 | // If we multiply by 2^52, we no longer have a fractional part | |
100 | // So input is an integer value already. | |
101 | ||
102 | // single | |
a334319f UD |
103 | // if the exponent is >= 10016 => 17(true) = 23(decimal) |
104 | // we have a significand of 53 bits 1.52-bits. (implicit 1) | |
105 | // If we multiply by 2^52, we no longer have a fractional part | |
8da2915d UD |
106 | // So input is an integer value already. |
107 | ||
a334319f UD |
108 | // If x is NAN, ZERO, or INFINITY, then return |
109 | ||
110 | // qnan snan inf norm unorm 0 -+ | |
111 | // 1 1 1 0 0 1 11 0xe7 | |
112 | ||
113 | ||
114 | .align 32 | |
115 | .global rint# | |
116 | ||
8da2915d | 117 | .section .text |
a334319f UD |
118 | .proc rint# |
119 | .align 32 | |
120 | ||
121 | ||
122 | rint: | |
123 | #ifdef _LIBC | |
124 | .global __rint | |
125 | .type __rint,@function | |
126 | __rint: | |
127 | #endif | |
8da2915d UD |
128 | |
129 | { .mfi | |
a334319f UD |
130 | mov rint_GR_fpsr = ar40 // Read the fpsr--need to check rc.s0 |
131 | fcvt.fx.s1 RINT_INT_f8 = f8 | |
132 | addl rint_GR_10033 = 0x10033, r0 | |
8da2915d UD |
133 | } |
134 | { .mfi | |
a334319f UD |
135 | mov rint_GR_FFFF = -1 |
136 | fnorm.s1 RINT_NORM_f8 = f8 | |
137 | mov rint_GR_17ones = 0x1FFFF | |
0ecb606c | 138 | ;; |
a334319f | 139 | } |
8da2915d UD |
140 | |
141 | { .mfi | |
a334319f UD |
142 | setf.sig RINT_FFFF = rint_GR_FFFF |
143 | fclass.m.unc p6,p0 = f8, 0xe7 | |
144 | mov rint_GR_rcs0_mask = 0x0c00 | |
8da2915d | 145 | ;; |
a334319f | 146 | } |
0ecb606c | 147 | |
0ecb606c | 148 | { .mfb |
a334319f UD |
149 | nop.m 999 |
150 | (p6) fnorm.d f8 = f8 | |
151 | (p6) br.ret.spnt b0 // Exit if x nan, inf, zero | |
0ecb606c | 152 | ;; |
a334319f | 153 | } |
8da2915d UD |
154 | |
155 | { .mfi | |
a334319f UD |
156 | nop.m 999 |
157 | fcvt.xf RINT_FLOAT_INT_f8 = RINT_INT_f8 | |
158 | nop.i 999 | |
8da2915d | 159 | ;; |
a334319f | 160 | } |
8da2915d | 161 | |
0ecb606c | 162 | { .mfi |
a334319f UD |
163 | getf.exp rint_GR_signexp = RINT_NORM_f8 |
164 | fcmp.eq.s0 p8,p0 = f8,f0 // Dummy op to set denormal | |
165 | nop.i 999 | |
8da2915d | 166 | ;; |
a334319f | 167 | } |
8da2915d | 168 | |
a334319f UD |
169 | |
170 | { .mii | |
171 | nop.m 999 | |
172 | nop.i 999 | |
173 | and rint_GR_exponent = rint_GR_signexp, rint_GR_17ones | |
174 | ;; | |
8da2915d | 175 | } |
a334319f UD |
176 | |
177 | { .mmi | |
178 | cmp.ge.unc p7,p6 = rint_GR_exponent, rint_GR_10033 | |
179 | and rint_GR_rcs0 = rint_GR_rcs0_mask, rint_GR_fpsr | |
180 | nop.i 999 | |
181 | ;; | |
8da2915d | 182 | } |
a334319f UD |
183 | |
184 | // Check to see if s0 rounding mode is round to nearest. If not then set s2 | |
185 | // rounding mode to that of s0 and repeat conversions. | |
186 | L(RINT_COMMON): | |
187 | { .mfb | |
188 | cmp.ne p11,p0 = rint_GR_rcs0, r0 | |
189 | (p6) fclass.m.unc p9,p10 = RINT_FLOAT_INT_f8, 0x07 // Test for result=0 | |
190 | (p11) br.cond.spnt L(RINT_NOT_ROUND_NEAREST) // Branch if not round to nearest | |
0ecb606c | 191 | ;; |
a334319f | 192 | } |
8da2915d | 193 | |
8da2915d | 194 | { .mfi |
a334319f UD |
195 | nop.m 999 |
196 | (p6) fcmp.eq.unc.s1 p0,p8 = RINT_FLOAT_INT_f8, RINT_NORM_f8 | |
197 | nop.i 999 | |
8da2915d | 198 | } |
a334319f UD |
199 | { .mfi |
200 | nop.m 999 | |
201 | (p7) fnorm.d.s0 f8 = f8 | |
202 | nop.i 999 | |
8da2915d | 203 | ;; |
a334319f | 204 | } |
0ecb606c | 205 | |
a334319f | 206 | // If result is zero, merge sign of input |
0ecb606c | 207 | { .mfi |
a334319f UD |
208 | nop.m 999 |
209 | (p9) fmerge.s f8 = f8, RINT_FLOAT_INT_f8 | |
210 | nop.i 999 | |
8da2915d | 211 | } |
a334319f UD |
212 | { .mfi |
213 | nop.m 999 | |
214 | (p10) fnorm.d f8 = RINT_FLOAT_INT_f8 | |
215 | nop.i 999 | |
0ecb606c | 216 | ;; |
a334319f | 217 | } |
0ecb606c | 218 | |
8da2915d | 219 | { .mfb |
a334319f UD |
220 | nop.m 999 |
221 | (p8) fmpy.s0 RINT_INEXACT = RINT_FFFF,RINT_FFFF // Dummy to set inexact | |
222 | br.ret.sptk b0 | |
0ecb606c | 223 | ;; |
8da2915d UD |
224 | } |
225 | ||
a334319f UD |
226 | L(RINT_NOT_ROUND_NEAREST): |
227 | // Set rounding mode of s2 to that of s0 | |
8da2915d | 228 | { .mfi |
a334319f UD |
229 | mov rint_GR_rcs0 = r0 // Clear so we don't come back here |
230 | fsetc.s2 0x7f, 0x40 | |
231 | nop.i 999 | |
8da2915d | 232 | ;; |
a334319f | 233 | } |
0ecb606c JJ |
234 | |
235 | { .mfi | |
a334319f UD |
236 | nop.m 999 |
237 | fcvt.fx.s2 RINT_INT_f8 = f8 | |
238 | nop.i 999 | |
0ecb606c | 239 | ;; |
a334319f | 240 | } |
8da2915d UD |
241 | |
242 | { .mfb | |
a334319f UD |
243 | nop.m 999 |
244 | fcvt.xf RINT_FLOAT_INT_f8 = RINT_INT_f8 | |
245 | br.cond.sptk L(RINT_COMMON) | |
0ecb606c | 246 | ;; |
a334319f UD |
247 | } |
248 | ||
8da2915d | 249 | |
a334319f UD |
250 | .endp rint |
251 | ASM_SIZE_DIRECTIVE(rint) | |
252 | #ifdef _LIBC | |
253 | ASM_SIZE_DIRECTIVE(__rint) | |
254 | #endif |