Updated to fedora-glibc-20050106T1443
[glibc.git] / sysdeps / ia64 / fpu / s_libm_ldexpl.S
blob72d45602cfbb0006cdc771ea6cdbe9a892fef028
1 .file "libm_ldexpl.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 ldexpl 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 // long double __libm_ldexpl  (long double x, int n, int int_type) 
51 // input  floating point f8 and int n (r34), int int_type (r35)
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_ldexpl)
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 = r34,r0  
108      fnorm.s1      FR_Norm_X  =   FR_Floating_X 
109      cmp.eq        p8,p9 = r35,r0  
113 //   Sign extend N if int is 32 bits
114 {    .mfi
115 (p9) mov           GR_N_as_int = r34     // Copy N if int is 64 bits
116      nop.f 0
117 (p8) sxt4          GR_N_as_int = r34     // 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.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.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 = 0x0000000000033FFF 
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= 0x0000000000013FFF 
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.s0        FR_Result = FR_Two_N,FR_Norm_X,f0 
218      nop.i         999
220 {    .mfi
221      nop.m         999
222      fma.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.s2        FR_Result2 = FR_Two_N,FR_Norm_X,f0 
228      nop.i         999
231 //   Check for overflow or underflow.
232 //   Restore s3
233 //   Restore s2
235 {    .mfi
236      nop.m 0
237      fsetc.s3      0x7F,0x40
238      nop.i 999 
240 {    .mfi
241      nop.m 0
242      fsetc.s2      0x7F,0x40
243      nop.i 999
247 //   Is the result zero?
249 {    .mfi
250      nop.m 999
251      fclass.m      p6, p0 =  FR_Result3, 0x007
252      nop.i 999 
254 {    .mfi
255      addl          GR_Tag = 144, r0
256      fcmp.ge.s1    p7, p8 = FR_Result2 , FR_Big
257      nop.i 0
261 //   Detect masked underflow - Tiny + Inexact Only
263 {    .mfi
264      nop.m 999
265 (p6) fcmp.neq.unc.s1 p6, p0 = FR_Result , FR_Result2
266      nop.i 999 
267 };; 
270 //   Is result bigger the allowed range?
271 //   Branch out for underflow
273 {    .mfb
274 (p6) addl           GR_Tag = 145, r0
275 (p8) fcmp.le.unc.s1 p9, p10 = FR_Result2 , FR_NBig
276 (p6) br.cond.spnt   LDEXPL_UNDERFLOW 
280 //   Branch out for overflow
282 { .mbb
283      nop.m 0
284 (p7) br.cond.spnt   LDEXPL_OVERFLOW 
285 (p9) br.cond.spnt   LDEXPL_OVERFLOW 
289 //   Return from main path.
291 {    .mfb
292      nop.m 999
293      nop.f 0
294      br.ret.sptk     b0;;                   
297 GLOBAL_LIBM_END(__libm_ldexpl)
298 __libm_error_region:
300 LDEXPL_OVERFLOW: 
301 LDEXPL_UNDERFLOW: 
304 // Get stack address of N
306 .prologue
307 { .mfi
308     add   GR_Parameter_Y=-32,sp         
309     nop.f 0
310 .save   ar.pfs,GR_SAVE_PFS
311     mov  GR_SAVE_PFS=ar.pfs              
314 // Adjust sp 
316 { .mfi
317 .fframe 64
318    add sp=-64,sp                         
319    nop.f 0
320    mov GR_SAVE_GP=gp       
324 //  Store N on stack in correct position 
325 //  Locate the address of x on stack
327 { .mmi
328    st8 [GR_Parameter_Y] =  GR_N_as_int,16       
329    add GR_Parameter_X = 16,sp          
330 .save   b0, GR_SAVE_B0
331    mov GR_SAVE_B0=b0                  
335 // Store x on the stack.
336 // Get address for result on stack.
338 .body
339 { .mib
340    stfe [GR_Parameter_X] = FR_Norm_X 
341    add   GR_Parameter_RESULT = 0,GR_Parameter_Y   
342    nop.b 0
344 { .mib
345    stfe [GR_Parameter_Y] = FR_Result                 
346    add   GR_Parameter_Y = -16,GR_Parameter_Y
347    br.call.sptk b0=__libm_error_support#   
351 //  Get location of result on stack
353 { .mmi
354    nop.m 0
355    nop.m 0
356    add   GR_Parameter_RESULT = 48,sp    
360 //  Get the new result 
362 { .mmi
363    ldfe  FR_Result = [GR_Parameter_RESULT]      
364 .restore sp
365    add   sp = 64,sp                       
366    mov   b0 = GR_SAVE_B0                  
370 //  Restore gp, ar.pfs and return
372 { .mib
373    mov   gp = GR_SAVE_GP                  
374    mov   ar.pfs = GR_SAVE_PFS             
375    br.ret.sptk     b0                  
378 LOCAL_LIBM_END(__libm_error_region)
380 .type   __libm_error_support#,@function
381 .global __libm_error_support#