Updated to fedora-glibc-20050106T1443
[glibc.git] / sysdeps / ia64 / fpu / libm_scalblnf.S
blob362e68b6417aaf113f59bfcc6a32a3a4a0b5bee1
1 .file "libm_scalblnf.s"
4 // Copyright (c) 2001 - 2003, Intel Corporation
5 // All rights reserved.
6 //
7 // Contributed 2001 by the Intel Numerics Group, Intel Corporation
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:
13 // * Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
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.
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.
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
28 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
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 
32 // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
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 // 
36 // Intel Corporation is the author of this code, and requests that all
37 // problem reports or change requests be submitted to it directly at 
38 // http://www.intel.com/software/products/opensource/libraries/num.htm.
40 // History
41 //==============================================================
42 // 08/03/01 Initial version
43 // 08/23/01 Corrected error tag number
44 // 02/06/02 Corrected to handle 32- or 64-bit integers
45 // 05/20/02 Cleaned up namespace and sf0 syntax
46 // 02/10/03 Reordered header: .section, .global, .proc, .align
48 // API
49 //==============================================================
50 // float = __libm_scalblnf  (float x, long int n, int long_int_type) 
51 // input  floating point f8 and long int n (r33) 
52 // input  long_int_type = 0 if long int defined as 32 bits, = 1 if 64 bits
53 // 
54 // output floating point f8
57 // Returns x* 2**n using an fma and detects overflow
58 // and underflow.   
62 FR_Big         = f6
63 FR_NBig        = f7
64 FR_Floating_X  = f8
65 FR_Result      = f8
66 FR_Result2     = f9
67 FR_Result3     = f11
68 FR_Norm_X      = f12
69 FR_Two_N       = f14
70 FR_Two_to_Big  = f15
72 GR_N_Biased    = r15
73 GR_Big         = r16
74 GR_NBig        = r17
75 GR_Scratch     = r18
76 GR_Scratch1    = r19
77 GR_Bias        = r20
78 GR_N_as_int    = r21
80 GR_SAVE_B0          = r32
81 GR_SAVE_GP          = r33
82 GR_SAVE_PFS         = r34
83 GR_Parameter_X      = r35
84 GR_Parameter_Y      = r36
85 GR_Parameter_RESULT = r37
86 GR_Tag              = r38
88 .section .text
89 GLOBAL_LIBM_ENTRY(__libm_scalblnf)
92 //   Is x NAN, INF, ZERO, +-?
93 //   Build the exponent Bias
95 {    .mfi
96      alloc         r32=ar.pfs,3,0,4,0
97      fclass.m.unc  p7,p0 = FR_Floating_X, 0xe7 //@snan | @qnan | @inf | @zero
98      addl          GR_Bias = 0x0FFFF,r0
103 //   Is N zero?
104 //   Normalize x
105 //   Do we need to sign extend input (long_int_type = 0)?
107 {    .mfi
108      cmp.eq.unc    p6,p0 = r33,r0  
109      fnorm.s1      FR_Norm_X  =   FR_Floating_X 
110      cmp.eq.unc    p8,p9 = r34,r0  
114 {    .mii
115 (p9) mov           GR_N_as_int = r33       // Get n directly if long int 64 bits
116 (p8) sxt4          GR_N_as_int = r33       // Sign extend n if long int 32 bits
117      nop.i         0
122 //   Normalize x
123 //   Branch and return special values.
124 //   Create -35000
125 //   Create 35000
127 {    .mfi
128      addl          GR_Big = 35000,r0
129      nop.f         0
130      add           GR_N_Biased = GR_Bias,GR_N_as_int
132 {    .mfb
133      addl          GR_NBig = -35000,r0
134 (p7) fma.s.s0      FR_Result = FR_Floating_X,f1, f0 
135 (p7) br.ret.spnt   b0  
139 //   Build the exponent Bias
140 //   Return x when N = 0
142 {    .mfi
143      setf.exp      FR_Two_N = GR_N_Biased                   
144      nop.f         0
145      addl          GR_Scratch1  = 0x063BF,r0 
147 {    .mfb
148      addl          GR_Scratch  = 0x019C3F,r0 
149 (p6) fma.s.s0      FR_Result = FR_Floating_X,f1, f0 
150 (p6) br.ret.spnt   b0  
154 //   Create 2*big
155 //   Create 2**-big 
156 //   Is N > 35000     
157 //   Is N < -35000     
158 //   Raise Denormal operand flag with compare
159 //   Main path, create 2**N
161 {    .mfi
162      setf.exp      FR_NBig = GR_Scratch1                  
163      nop.f         0
164      cmp.ge.unc    p6, p0 = GR_N_as_int, GR_Big
166 {    .mfi
167      setf.exp      FR_Big = GR_Scratch                  
168      fcmp.ge.s0    p0,p11 = FR_Floating_X,f0
169      cmp.le.unc    p8, p0 = GR_N_as_int, GR_NBig
173 //   Adjust 2**N if N was very small or very large
175 {    .mfi
176      nop.m 0
177 (p6) fma.s1        FR_Two_N = FR_Big,f1,f0
178      nop.i 0
180 { .mlx
181      nop.m 999
182      movl          GR_Scratch = 0x000000000003007F 
186 {    .mfi
187      nop.m 0
188 (p8) fma.s1        FR_Two_N = FR_NBig,f1,f0
189      nop.i 0
191 {    .mlx
192      nop.m 999
193      movl          GR_Scratch1= 0x000000000001007F 
196 //   Set up necessary status fields 
198 //   S0 user supplied status
199 //   S2 user supplied status + WRE + TD  (Overflows)
200 //   S3 user supplied status + FZ + TD   (Underflows)
202 {    .mfi
203      nop.m 999
204      fsetc.s3      0x7F,0x41
205      nop.i 999
207 {    .mfi
208      nop.m 999
209      fsetc.s2      0x7F,0x42
210      nop.i 999
214 //   Do final operation
216 {    .mfi
217      setf.exp      FR_NBig = GR_Scratch
218      fma.s.s0      FR_Result = FR_Two_N,FR_Norm_X,f0 
219      nop.i         999
221 {    .mfi
222      nop.m         999
223      fma.s.s3      FR_Result3 = FR_Two_N,FR_Norm_X,f0 
224      nop.i         999
226 {    .mfi
227      setf.exp      FR_Big = GR_Scratch1
228      fma.s.s2      FR_Result2 = FR_Two_N,FR_Norm_X,f0 
229      nop.i         999
232 //   Check for overflow or underflow.
233 //   Restore s3
234 //   Restore s2
236 {    .mfi
237      nop.m 0
238      fsetc.s3      0x7F,0x40
239      nop.i 999 
241 {    .mfi
242      nop.m 0
243      fsetc.s2      0x7F,0x40
244      nop.i 999
248 //   Is the result zero?
250 {    .mfi
251      nop.m 999
252      fclass.m.unc  p6, p0 =  FR_Result3, 0x007
253      nop.i 999 
255 {    .mfi
256      addl          GR_Tag = 205, r0
257      fcmp.ge.unc.s1 p7, p8 = FR_Result2 , FR_Big
258      nop.i 0
262 //   Detect masked underflow - Tiny + Inexact Only
264 {    .mfi
265      nop.m 999
266 (p6) fcmp.neq.unc.s1 p6, p0 = FR_Result , FR_Result2
267      nop.i 999 
268 };; 
271 //   Is result bigger the allowed range?
272 //   Branch out for underflow
274 {    .mfb
275 (p6) addl           GR_Tag = 206, r0
276 (p8) fcmp.le.unc.s1 p9, p10 = FR_Result2 , FR_NBig
277 (p6) br.cond.spnt   scalbnf_UNDERFLOW 
281 //   Branch out for overflow
283 { .mbb
284      nop.m 0
285 (p7) br.cond.spnt   scalbnf_OVERFLOW 
286 (p9) br.cond.spnt   scalbnf_OVERFLOW 
290 //   Return from main path.
292 {    .mfb
293      nop.m 999
294      nop.f 0
295      br.ret.sptk     b0;;                   
298 GLOBAL_LIBM_END(__libm_scalblnf)
299 __libm_error_region:
301 scalbnf_OVERFLOW: 
302 scalbnf_UNDERFLOW: 
305 // Get stack address of N
307 .prologue
308 { .mfi
309     add   GR_Parameter_Y=-32,sp         
310     nop.f 0
311 .save   ar.pfs,GR_SAVE_PFS
312     mov  GR_SAVE_PFS=ar.pfs              
315 // Adjust sp 
317 { .mfi
318 .fframe 64
319    add sp=-64,sp                         
320    nop.f 0
321    mov GR_SAVE_GP=gp       
325 //  Store N on stack in correct position 
326 //  Locate the address of x on stack
328 { .mmi
329    st8 [GR_Parameter_Y] =  GR_N_as_int,16       
330    add GR_Parameter_X = 16,sp          
331 .save   b0, GR_SAVE_B0
332    mov GR_SAVE_B0=b0                  
336 // Store x on the stack.
337 // Get address for result on stack.
339 .body
340 { .mib
341    stfs [GR_Parameter_X] = FR_Norm_X 
342    add   GR_Parameter_RESULT = 0,GR_Parameter_Y   
343    nop.b 0
345 { .mib
346    stfs [GR_Parameter_Y] = FR_Result                 
347    add   GR_Parameter_Y = -16,GR_Parameter_Y
348    br.call.sptk b0=__libm_error_support#   
352 //  Get location of result on stack
354 { .mmi
355    nop.m 0
356    nop.m 0
357    add   GR_Parameter_RESULT = 48,sp    
361 //  Get the new result 
363 { .mmi
364    ldfs  FR_Result = [GR_Parameter_RESULT]      
365 .restore sp
366    add   sp = 64,sp                       
367    mov   b0 = GR_SAVE_B0                  
371 //  Restore gp, ar.pfs and return
373 { .mib
374    mov   gp = GR_SAVE_GP                  
375    mov   ar.pfs = GR_SAVE_PFS             
376    br.ret.sptk     b0                  
379 LOCAL_LIBM_END(__libm_error_region)
381 .type   __libm_error_support#,@function
382 .global __libm_error_support#