Updated to fedora-glibc-20050106T1443
[glibc.git] / sysdeps / ia64 / fpu / s_libm_ldexp.S
blob1fc2c3f80ca2a00f293e003c724841f6c8526660
1 .file "libm_ldexp.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 ldexp 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 // double __libm_ldexp  (double 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_ldexp)
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
102 //   Is N zero?
103 //   Normalize x
104 //   Is integer type 32 bits?
106 {    .mfi
107      cmp.eq        p6,p0 = r33,r0  
108      fnorm.s1      FR_Norm_X  =   FR_Floating_X 
109      cmp.eq        p8,p9 = r34,r0  
113 //   Sign extend N if int is 32 bits
114 {    .mfi
115 (p9) mov           GR_N_as_int = r33     // Copy N if int is 64 bits
116      nop.f 0
117 (p8) sxt4          GR_N_as_int = r33     // Sign extend N if int is 32 bits
122 //   Branch and return special values.
123 //   Create -35000
124 //   Create 35000
126 {    .mfi
127      addl          GR_Big = 35000,r0
128      nop.f         0
129      add           GR_N_Biased = GR_Bias,GR_N_as_int
131 {    .mfb
132      addl          GR_NBig = -35000,r0
133 (p7) fma.d.s0      FR_Result = FR_Floating_X,f1, f0 
134 (p7) br.ret.spnt   b0  
138 //   Build the exponent Bias
139 //   Return x when N = 0
141 {    .mfi
142      setf.exp      FR_Two_N = GR_N_Biased                   
143      nop.f         0
144      addl          GR_Scratch1  = 0x063BF,r0 
146 {    .mfb
147      addl          GR_Scratch  = 0x019C3F,r0 
148 (p6) fma.d.s0      FR_Result = FR_Floating_X,f1, f0 
149 (p6) br.ret.spnt   b0  
153 //   Create 2*big
154 //   Create 2**-big 
155 //   Is N > 35000     
156 //   Is N < -35000     
157 //   Raise Denormal operand flag with compare
158 //   Main path, create 2**N
160 {    .mfi
161      setf.exp      FR_NBig = GR_Scratch1                  
162      nop.f         0
163      cmp.ge        p6, p0 = GR_N_as_int, GR_Big
165 {    .mfi
166      setf.exp      FR_Big = GR_Scratch                  
167      fcmp.ge.s0    p0,p11 = FR_Floating_X,f0
168      cmp.le        p8, p0 = GR_N_as_int, GR_NBig
172 //   Adjust 2**N if N was very small or very large
174 {    .mfi
175      nop.m 0
176 (p6) fma.s1        FR_Two_N = FR_Big,f1,f0
177      nop.i 0
179 { .mlx
180      nop.m 999
181      movl          GR_Scratch = 0x00000000000303FF 
185 {    .mfi
186      nop.m 0
187 (p8) fma.s1        FR_Two_N = FR_NBig,f1,f0
188      nop.i 0
190 {    .mlx
191      nop.m 999
192      movl          GR_Scratch1= 0x00000000000103FF 
195 //   Set up necessary status fields 
197 //   S0 user supplied status
198 //   S2 user supplied status + WRE + TD  (Overflows)
199 //   S3 user supplied status + FZ + TD   (Underflows)
201 {    .mfi
202      nop.m 999
203      fsetc.s3      0x7F,0x41
204      nop.i 999
206 {    .mfi
207      nop.m 999
208      fsetc.s2      0x7F,0x42
209      nop.i 999
213 //   Do final operation
215 {    .mfi
216      setf.exp      FR_NBig = GR_Scratch
217      fma.d.s0      FR_Result = FR_Two_N,FR_Norm_X,f0 
218      nop.i         999
220 {    .mfi
221      nop.m         999
222      fma.d.s3      FR_Result3 = FR_Two_N,FR_Norm_X,f0 
223      nop.i         999
225 {    .mfi
226      setf.exp      FR_Big = GR_Scratch1
227      fma.d.s2      FR_Result2 = FR_Two_N,FR_Norm_X,f0 
228      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      p6, p0 =  FR_Result3, 0x007
253      nop.i 999 
255 {    .mfi
256      addl          GR_Tag = 146, r0
257      fcmp.ge.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 = 147, r0
276 (p8) fcmp.le.unc.s1 p9, p10 = FR_Result2 , FR_NBig
277 (p6) br.cond.spnt   LDEXP_UNDERFLOW 
281 //   Branch out for overflow
283 { .mbb
284      nop.m 0
285 (p7) br.cond.spnt    LDEXP_OVERFLOW 
286 (p9) br.cond.spnt    LDEXP_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_ldexp)
299 __libm_error_region:
301 LDEXP_OVERFLOW: 
302 LDEXP_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    stfd [GR_Parameter_X] = FR_Norm_X 
342    add   GR_Parameter_RESULT = 0,GR_Parameter_Y   
343    nop.b 0
345 { .mib
346    stfd [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    ldfd  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#