]>
Commit | Line | Data |
---|---|---|
d5efd131 MF |
1 | .file "ilogb.s" |
2 | ||
3 | ||
4 | // Copyright (c) 2000 - 2003, Intel Corporation | |
5 | // All rights reserved. | |
6 | // | |
d5efd131 MF |
7 | // |
8 | // Redistribution and use in source and binary forms, with or without | |
9 | // modification, are permitted provided that the following conditions are | |
10 | // met: | |
11 | // | |
12 | // * Redistributions of source code must retain the above copyright | |
13 | // notice, this list of conditions and the following disclaimer. | |
14 | // | |
15 | // * Redistributions in binary form must reproduce the above copyright | |
16 | // notice, this list of conditions and the following disclaimer in the | |
17 | // documentation and/or other materials provided with the distribution. | |
18 | // | |
19 | // * The name of Intel Corporation may not be used to endorse or promote | |
20 | // products derived from this software without specific prior written | |
21 | // permission. | |
22 | ||
23 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
24 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
25 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
26 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS | |
27 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
28 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
29 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
30 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
31 | // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING | |
32 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
33 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
34 | // | |
35 | // Intel Corporation is the author of this code, and requests that all | |
36 | // problem reports or change requests be submitted to it directly at | |
37 | // http://www.intel.com/software/products/opensource/libraries/num.htm. | |
38 | // | |
39 | // History | |
40 | //============================================================== | |
41 | // 02/03/00 Initial version | |
42 | // 05/26/00 Fix bug when x a double-extended denormal; | |
43 | // if x=0 call error routine, per C9X | |
44 | // 08/15/00 Bundle added after call to __libm_error_support to properly | |
45 | // set [the previously overwritten] GR_Parameter_RESULT. | |
46 | // 01/20/01 Fixed result for x=0, corrected error tag value. | |
47 | // 05/20/02 Cleaned up namespace and sf0 syntax | |
48 | // 01/20/03 Improved performance | |
49 | // | |
50 | // API | |
51 | //============================================================== | |
52 | // int ilogb( double x ); | |
53 | // | |
54 | // Overview of operation | |
55 | //============================================================== | |
56 | // The ilogb function extracts the exponent of x as an integer | |
57 | // and returns it in r8 | |
58 | // | |
59 | // ilogb is similar to logb but differs in the following ways: | |
60 | // +-inf | |
61 | // ilogb: returns INT_MAX | |
62 | // logb: returns +inf | |
63 | // Nan returns FP_LOGBNAN (which is either INT_MAX or INT_MIN) | |
64 | // ilogb: returns INT_MAX (7fffffff) | |
65 | // logb: returns QNAN (quietized SNAN) | |
66 | // 0 returns FP_ILOGB0 (which is either INT_MIN or -INT_MAX) | |
67 | // ilogb: returns -INT_MAX (80000001) | |
68 | // logb: returns -inf, raises the divide-by-zero exception, | |
69 | // and calls libm_error_support to set domain error | |
70 | // | |
71 | // Registers used | |
72 | //============================================================== | |
73 | // general registers used: | |
74 | // r26 -> r39 | |
75 | // r36 -> r39 used as parameters to error path | |
76 | // | |
77 | // predicate registers used: | |
78 | // p6 -> p10 | |
79 | // floating-point registers used: | |
80 | // f9, f10, f11 | |
81 | // f8, input | |
82 | ||
83 | rExpBias = r26 | |
84 | rExpMask = r27 | |
85 | rSignexp_x = r28 | |
86 | rExp_x = r29 | |
87 | rIntMax = r30 | |
88 | rExp_2to64 = r31 | |
89 | ||
90 | GR_SAVE_PFS = r32 | |
91 | rTrialResult = r33 | |
92 | GR_SAVE_B0 = r34 | |
93 | GR_SAVE_GP = r35 | |
94 | ||
95 | GR_Parameter_X = r36 | |
96 | GR_Parameter_Y = r37 | |
97 | GR_Parameter_RESULT = r38 | |
98 | GR_Parameter_TAG = r39 | |
99 | ||
100 | fTmp = f9 | |
101 | fNorm_x = f10 | |
102 | f2to64 = f11 | |
103 | ||
104 | .section .text | |
105 | GLOBAL_LIBM_ENTRY(ilogb) | |
106 | ||
107 | // X NORMAL | |
108 | // TrueExp_x = exp(f8) - 0xffff | |
109 | // r8 = TrueExp_x | |
110 | { .mfi | |
111 | getf.exp rSignexp_x = f8 | |
112 | fclass.m p8,p0 = f8, 0x0b // Test for x unorm | |
113 | mov rExpBias = 0xffff // Exponent bias | |
114 | } | |
115 | { .mfi | |
116 | nop.m 0 | |
117 | fnorm.s1 fNorm_x = f8 | |
118 | mov rExpMask = 0x1ffff // Exponent mask | |
119 | } | |
120 | ;; | |
121 | ||
122 | // Form signexp of 2^64 in case need to scale denormal | |
123 | { .mfb | |
124 | mov rExp_2to64 = 0x1003f | |
125 | fclass.m p6,p9 = f8, 0x1e3 // Test x natval, nan, inf | |
126 | (p8) br.cond.spnt ILOGB_DENORM // Branch if x unorm | |
127 | } | |
128 | ;; | |
129 | ||
130 | ILOGB_COMMON: | |
131 | // Return here from ILOGB_DENORM | |
132 | { .mfi | |
133 | and rExp_x = rSignexp_x, rExpMask // Get biased exponent | |
134 | fclass.m p7,p10 = f8, 0x07 // Test x zero | |
135 | nop.i 0 | |
136 | } | |
137 | { .mlx | |
138 | nop.m 0 | |
139 | movl rIntMax = 0x000000007fffffff // Form INT_MAX | |
140 | } | |
141 | ;; | |
142 | ||
143 | .pred.rel "mutex",p6,p9 | |
144 | { .mfi | |
145 | (p9) sub r8 = rExp_x, rExpBias // Get true exponent for normal path | |
146 | (p6) fma.s0 fTmp = f8, f8, f0 // Dummy to set Invalid flag | |
147 | (p6) mov r8 = rIntMax // If nan, inf, return INT_MAX | |
148 | } | |
149 | { .mbb | |
150 | nop.m 0 | |
151 | (p7) br.cond.spnt ILOGB_ZERO // Branch if x zero | |
152 | (p10) br.ret.sptk b0 // Exit if x not zero | |
153 | } | |
154 | ;; | |
155 | ||
156 | ||
157 | ILOGB_DENORM: | |
158 | // Form 2^64 in case need to scale denormal | |
159 | // Check to see if double-extended denormal | |
160 | { .mfi | |
161 | setf.exp f2to64 = rExp_2to64 | |
162 | fclass.m p8,p0 = fNorm_x, 0x0b | |
163 | nop.i 0 | |
164 | } | |
165 | ;; | |
166 | ||
167 | { .mfi | |
168 | nop.m 0 | |
169 | fcmp.eq.s0 p7,p0 = f8, f0 // Dummy op to set denormal flag | |
170 | nop.i 0 | |
171 | } | |
172 | ;; | |
173 | ||
174 | // If double-extended denormal add 64 to exponent bias for scaling | |
175 | // If double-extended denormal form x * 2^64 which is normal | |
176 | { .mfi | |
177 | (p8) add rExpBias = 64, rExpBias | |
178 | (p8) fmpy.s1 fNorm_x = fNorm_x, f2to64 | |
179 | nop.i 0 | |
180 | } | |
181 | ;; | |
182 | ||
183 | // Logic is the same as normal path but use normalized input | |
184 | { .mib | |
185 | getf.exp rSignexp_x = fNorm_x | |
186 | nop.i 0 | |
187 | br.cond.sptk ILOGB_COMMON // Return to main path | |
188 | } | |
189 | ;; | |
190 | ||
191 | ILOGB_ZERO: | |
192 | // Here if x zero | |
193 | // Return INT_MIN, call error support | |
194 | ||
195 | { .mlx | |
196 | alloc r32=ar.pfs,1,3,4,0 | |
197 | movl rTrialResult = 0x0000000080000000 | |
198 | } | |
199 | { .mib | |
200 | mov GR_Parameter_TAG = 157 // Error code | |
201 | nop.i 0 | |
202 | br.cond.sptk __libm_error_region // Call error support | |
203 | } | |
204 | ;; | |
205 | ||
206 | GLOBAL_LIBM_END(ilogb) | |
207 | ||
208 | ||
209 | LOCAL_LIBM_ENTRY(__libm_error_region) | |
210 | .prologue | |
211 | ||
212 | { .mfi | |
213 | add GR_Parameter_Y=-32,sp // Parameter 2 value | |
214 | nop.f 0 | |
215 | .save ar.pfs,GR_SAVE_PFS | |
216 | mov GR_SAVE_PFS=ar.pfs // Save ar.pfs | |
217 | } | |
218 | { .mfi | |
219 | .fframe 64 | |
220 | add sp=-64,sp // Create new stack | |
221 | nop.f 0 | |
222 | mov GR_SAVE_GP=gp // Save gp | |
223 | };; | |
224 | ||
225 | { .mmi | |
226 | stfd [GR_Parameter_Y] = f0,16 // STORE Parameter 2 on stack | |
227 | add GR_Parameter_X = 16,sp // Parameter 1 address | |
228 | .save b0, GR_SAVE_B0 | |
229 | mov GR_SAVE_B0=b0 // Save b0 | |
230 | };; | |
231 | ||
232 | .body | |
233 | { .mib | |
234 | stfd [GR_Parameter_X] = f8 // STORE Parameter 1 on stack | |
235 | add GR_Parameter_RESULT = 0,GR_Parameter_Y // Parameter 3 address | |
236 | nop.b 0 | |
237 | } | |
238 | { .mib | |
239 | stfd [GR_Parameter_Y] = f9 // Store Parameter 3 on stack | |
240 | add GR_Parameter_Y = -16,GR_Parameter_Y | |
241 | br.call.sptk b0=__libm_error_support# // Call error handling function | |
242 | };; | |
243 | ||
244 | { .mmi | |
245 | add GR_Parameter_RESULT = 48,sp | |
246 | nop.m 0 | |
247 | nop.i 0 | |
248 | };; | |
249 | ||
250 | { .mmi | |
251 | mov r8 = rTrialResult | |
252 | .restore sp | |
253 | add sp = 64,sp // Restore stack pointer | |
254 | mov b0 = GR_SAVE_B0 // Restore return address | |
255 | };; | |
256 | ||
257 | { .mib | |
258 | mov gp = GR_SAVE_GP // Restore gp | |
259 | mov ar.pfs = GR_SAVE_PFS // Restore ar.pfs | |
260 | br.ret.sptk b0 | |
261 | };; | |
262 | ||
263 | LOCAL_LIBM_END(__libm_error_region) | |
264 | ||
265 | ||
266 | .type __libm_error_support#,@function | |
267 | .global __libm_error_support# |