Updated to fedora-glibc-20050106T1443
[glibc.git] / sysdeps / ia64 / fpu / s_libm_ldexpf.S
blobd7f161c93d7b8b6faf95fd59ec2cb068e1c9b005
1 .file "libm_ldexpf.s"
4 // Copyright (c) 2000 - 2003, Intel Corporation
5 // All rights reserved.
6 //
7 // Contributed 2000 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 // 02/02/00 Initial version
43 // 01/26/01 ldexpf completely reworked and now standalone version 
44 // 01/04/02 Added handling for int 32 or 64 bits
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_ldexpf  (float x, int n, int int_type) 
51 // input  floating point f8 and int n (r33), int int_type (r34)
52 // output floating point f8
54 // int_type = 0 if int is 32 bits
55 // int_type = 1 if int is 64 bits
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_ldexpf)
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      p7,p0 = FR_Floating_X, 0xe7 //@snan | @qnan | @inf | @zero
98      addl          GR_Bias = 0x0FFFF,r0
101 //   Is N zero?
102 //   Normalize x
103 //   Is integer type 32 bits?
105 {    .mfi
106      cmp.eq        p6,p0 = r33,r0  
107      fnorm.s1      FR_Norm_X  =   FR_Floating_X 
108      cmp.eq        p8,p9 = r34,r0  
112 //   Sign extend N if int is 32 bits
113 {    .mfi
114 (p9) mov           GR_N_as_int = r33     // Copy N if int is 64 bits
115      nop.f 0
116 (p8) sxt4          GR_N_as_int = r33     // Sign extend N if int is 32 bits
121 //   Branch and return special values.
122 //   Create -35000
123 //   Create 35000
125 {    .mfi
126      addl          GR_Big = 35000,r0
127      nop.f         0
128      add           GR_N_Biased = GR_Bias,GR_N_as_int
130 {    .mfb
131      addl          GR_NBig = -35000,r0
132 (p7) fma.s.s0      FR_Result = FR_Floating_X,f1, f0 
133 (p7) br.ret.spnt   b0  
137 //   Build the exponent Bias
138 //   Return x when N = 0
140 {    .mfi
141      setf.exp      FR_Two_N = GR_N_Biased                   
142      nop.f         0
143      addl          GR_Scratch1  = 0x063BF,r0 
145 {    .mfb
146      addl          GR_Scratch  = 0x019C3F,r0 
147 (p6) fma.s.s0      FR_Result = FR_Floating_X,f1, f0 
148 (p6) br.ret.spnt   b0  
152 //   Create 2*big
153 //   Create 2**-big 
154 //   Is N > 35000     
155 //   Is N < -35000     
156 //   Raise Denormal operand flag with compare
157 //   Main path, create 2**N
159 {    .mfi
160      setf.exp      FR_NBig = GR_Scratch1                  
161      nop.f         0
162      cmp.ge        p6, p0 = GR_N_as_int, GR_Big
164 {    .mfi
165      setf.exp      FR_Big = GR_Scratch                  
166      fcmp.ge.s0    p0,p11 = FR_Floating_X,f0
167      cmp.le        p8, p0 = GR_N_as_int, GR_NBig
171 //   Adjust 2**N if N was very small or very large
173 {    .mfi
174      nop.m 0
175 (p6) fma.s1        FR_Two_N = FR_Big,f1,f0
176      nop.i 0
178 { .mlx
179      nop.m 999
180      movl          GR_Scratch = 0x000000000003007F 
184 {    .mfi
185      nop.m 0
186 (p8) fma.s1        FR_Two_N = FR_NBig,f1,f0
187      nop.i 0
189 {    .mlx
190      nop.m 999
191      movl          GR_Scratch1= 0x000000000001007F 
194 //   Set up necessary status fields 
196 //   S0 user supplied status
197 //   S2 user supplied status + WRE + TD  (Overflows)
198 //   S3 user supplied status + FZ + TD   (Underflows)
200 {    .mfi
201      nop.m 999
202      fsetc.s3      0x7F,0x41
203      nop.i 999
205 {    .mfi
206      nop.m 999
207      fsetc.s2      0x7F,0x42
208      nop.i 999
212 //   Do final operation
214 {    .mfi
215      setf.exp      FR_NBig = GR_Scratch
216      fma.s.s0      FR_Result = FR_Two_N,FR_Norm_X,f0 
217      nop.i         999
219 {    .mfi
220      nop.m         999
221      fma.s.s3      FR_Result3 = FR_Two_N,FR_Norm_X,f0 
222      nop.i         999
224 {    .mfi
225      setf.exp      FR_Big = GR_Scratch1
226      fma.s.s2      FR_Result2 = FR_Two_N,FR_Norm_X,f0 
227      nop.i         999
230 //   Check for overflow or underflow.
231 //   Restore s3
232 //   Restore s2
234 {    .mfi
235      nop.m 0
236      fsetc.s3      0x7F,0x40
237      nop.i 999 
239 {    .mfi
240      nop.m 0
241      fsetc.s2      0x7F,0x40
242      nop.i 999
246 //   Is the result zero?
248 {    .mfi
249      nop.m 999
250      fclass.m      p6, p0 =  FR_Result3, 0x007
251      nop.i 999 
253 {    .mfi
254      addl          GR_Tag = 148, r0
255      fcmp.ge.s1    p7, p8 = FR_Result2 , FR_Big
256      nop.i 0
260 //   Detect masked underflow - Tiny + Inexact Only
262 {    .mfi
263      nop.m 999
264 (p6) fcmp.neq.unc.s1 p6, p0 = FR_Result , FR_Result2
265      nop.i 999 
266 };; 
269 //   Is result bigger the allowed range?
270 //   Branch out for underflow
272 {    .mfb
273 (p6) addl           GR_Tag = 149, r0
274 (p8) fcmp.le.unc.s1 p9, p10 = FR_Result2 , FR_NBig
275 (p6) br.cond.spnt   LDEXPF_UNDERFLOW 
279 //   Branch out for overflow
281 { .mbb
282      nop.m 0
283 (p7) br.cond.spnt   LDEXPF_OVERFLOW 
284 (p9) br.cond.spnt   LDEXPF_OVERFLOW 
288 //   Return from main path.
290 {    .mfb
291      nop.m 999
292      nop.f 0
293      br.ret.sptk     b0;;                   
296 GLOBAL_LIBM_END(__libm_ldexpf)
297 __libm_error_region:
299 LDEXPF_OVERFLOW: 
300 LDEXPF_UNDERFLOW: 
303 // Get stack address of N
305 .prologue
306 { .mfi
307     add   GR_Parameter_Y=-32,sp         
308     nop.f 0
309 .save   ar.pfs,GR_SAVE_PFS
310     mov  GR_SAVE_PFS=ar.pfs              
313 // Adjust sp 
315 { .mfi
316 .fframe 64
317    add sp=-64,sp                         
318    nop.f 0
319    mov GR_SAVE_GP=gp       
323 //  Store N on stack in correct position 
324 //  Locate the address of x on stack
326 { .mmi
327    st8 [GR_Parameter_Y] =  GR_N_as_int,16       
328    add GR_Parameter_X = 16,sp          
329 .save   b0, GR_SAVE_B0
330    mov GR_SAVE_B0=b0                  
334 // Store x on the stack.
335 // Get address for result on stack.
337 .body
338 { .mib
339    stfs [GR_Parameter_X] = FR_Norm_X 
340    add   GR_Parameter_RESULT = 0,GR_Parameter_Y   
341    nop.b 0
343 { .mib
344    stfs [GR_Parameter_Y] = FR_Result                 
345    add   GR_Parameter_Y = -16,GR_Parameter_Y
346    br.call.sptk b0=__libm_error_support#   
350 //  Get location of result on stack
352 { .mmi
353    nop.m 0
354    nop.m 0
355    add   GR_Parameter_RESULT = 48,sp    
359 //  Get the new result 
361 { .mmi
362    ldfs  FR_Result = [GR_Parameter_RESULT]      
363 .restore sp
364    add   sp = 64,sp                       
365    mov   b0 = GR_SAVE_B0                  
369 //  Restore gp, ar.pfs and return
371 { .mib
372    mov   gp = GR_SAVE_GP                  
373    mov   ar.pfs = GR_SAVE_PFS             
374    br.ret.sptk     b0                  
377 LOCAL_LIBM_END(__libm_error_region)
379 .type   __libm_error_support#,@function
380 .global __libm_error_support#