(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / sysdeps / ia64 / fpu / s_ldexp.S
blob4dcd671c9fb372e6b2ff809e1fb73b9df45042f9
1 .file "ldexp.s"
3 // Copyright (C) 2000, 2001, Intel Corporation
4 // All rights reserved.
5 // 
6 // Contributed 2/2/2000 by John Harrison, Ted Kubaska, Bob Norin, Shane Story,
7 // and Ping Tak Peter Tang of the Computational Software Lab, 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://developer.intel.com/opensource.
40 // History
41 //==============================================================
42 // 2/02/00  Initial version
43 // 1/26/01  ldex pcompletely reworked and now standalone version 
45 // API
46 //==============================================================
47 // double = ldexp  (double x, int n) 
48 // input  floating point f8 and int n (r33) 
49 // output floating point f8
51 // Returns x* 2**n using an fma and detects overflow
52 // and underflow.   
56 #include "libm_support.h"
58 FR_Big         = f6
59 FR_NBig        = f7
60 FR_Floating_X  = f8
61 FR_Result      = f8
62 FR_Result2     = f9
63 FR_Result3     = f11
64 FR_Norm_X      = f12
65 FR_Two_N       = f14
66 FR_Two_to_Big  = f15
68 GR_N_Biased    = r15
69 GR_Big         = r16
70 GR_NBig        = r17
71 GR_Scratch     = r18
72 GR_Scratch1    = r19
73 GR_Bias        = r20
74 GR_N_as_int    = r21
76 GR_SAVE_B0          = r32
77 GR_SAVE_GP          = r33
78 GR_SAVE_PFS         = r34
79 GR_Parameter_X      = r35
80 GR_Parameter_Y      = r36
81 GR_Parameter_RESULT = r37
82 GR_Tag              = r38
84 .align 32
85 .global ldexp
87 .section .text
88 .proc  ldexp
89 .align 32
91 ldexp: 
94 //   Is x NAN, INF, ZERO, +-?
95 //   Build the exponent Bias
97 {    .mfi
98      alloc         r32=ar.pfs,1,2,4,0
99      fclass.m.unc  p7,p0 = FR_Floating_X, 0xe7 //@snan | @qnan | @inf | @zero
100      addl          GR_Bias = 0x0FFFF,r0
104 //   Sign extend input
105 //   Is N zero?
106 //   Normalize x
108 {    .mfi
109      cmp.eq.unc    p6,p0 = r33,r0  
110      fnorm.s1      FR_Norm_X  =   FR_Floating_X 
111      sxt4          GR_N_as_int = r33
116 //   Normalize x
117 //   Branch and return special values.
118 //   Create -35000
119 //   Create 35000
121 {    .mfi
122      addl          GR_Big = 35000,r0
123      nop.f 0
124      add           GR_N_Biased = GR_Bias,GR_N_as_int
126 {    .mfb
127      addl          GR_NBig = -35000,r0
128 (p7) fma.d.s0      FR_Result = FR_Floating_X,f1, f0 
129 (p7) br.ret.spnt   b0  
133 //   Build the exponent Bias
134 //   Return x when N = 0
136 {    .mfi
137      setf.exp      FR_Two_N = GR_N_Biased                   
138      nop.f 0
139      addl          GR_Scratch1  = 0x063BF,r0 
141 {    .mfb
142      addl          GR_Scratch  = 0x019C3F,r0 
143 (p6) fma.d.s0      FR_Result = FR_Floating_X,f1, f0 
144 (p6) br.ret.spnt   b0  
148 //   Create 2*big
149 //   Create 2**-big 
150 //   Is N > 35000     
151 //   Is N < -35000     
152 //   Raise Denormal operand flag with compare
153 //   Main path, create 2**N
155 {    .mfi
156      setf.exp      FR_NBig = GR_Scratch1                  
157      nop.f 0
158      cmp.ge.unc    p6, p0 = GR_N_as_int, GR_Big
160 {    .mfi
161      setf.exp      FR_Big = GR_Scratch                  
162      fcmp.ge.s0    p0,p11 = FR_Floating_X,f0
163      cmp.le.unc    p8, p0 = GR_N_as_int, GR_NBig
167 //   Adjust 2**N if N was very small or very large
169 {    .mfi
170      nop.m 0
171 (p6) fma.s1        FR_Two_N = FR_Big,f1,f0
172      nop.i 0
174 { .mlx
175      nop.m 999
176 (p0) movl          GR_Scratch = 0x00000000000303FF 
180 {    .mfi
181      nop.m 0
182 (p8) fma.s1        FR_Two_N = FR_NBig,f1,f0
183      nop.i 0
185 {    .mlx
186      nop.m 999
187 (p0) movl          GR_Scratch1= 0x00000000000103FF 
190 //   Set up necessary status fields 
192 //   S0 user supplied status
193 //   S2 user supplied status + WRE + TD  (Overflows)
194 //   S3 user supplied status + FZ + TD   (Underflows)
196 {    .mfi
197      nop.m 999
198 (p0) fsetc.s3      0x7F,0x41
199      nop.i 999
201 {    .mfi
202      nop.m 999
203 (p0) fsetc.s2      0x7F,0x42
204      nop.i 999
208 //   Do final operation
210 {    .mfi
211      setf.exp     FR_NBig = GR_Scratch
212      fma.d.s0     FR_Result = FR_Two_N,FR_Norm_X,f0 
213      nop.i                           999
215 {    .mfi
216      nop.m                           999
217      fma.d.s3     FR_Result3 = FR_Two_N,FR_Norm_X,f0 
218      nop.i                           999
220 {    .mfi
221      setf.exp     FR_Big = GR_Scratch1
222      fma.d.s2     FR_Result2 = FR_Two_N,FR_Norm_X,f0 
223      nop.i                           999
227 //   Check for overflow or underflow.
228 //   Restore s3
229 //   Restore s2
231 {    .mfi
232      nop.m 0
233      fsetc.s3     0x7F,0x40
234      nop.i 999 
236 {    .mfi
237      nop.m 0
238      fsetc.s2     0x7F,0x40
239      nop.i 999
243 //   Is the result zero?
245 {    .mfi
246      nop.m 999
247      fclass.m.unc p6, p0 =  FR_Result3, 0x007
248      nop.i 999 
250 {    .mfi
251      addl           GR_Tag = 146, r0
252      fcmp.ge.unc.s1 p7, p8 = FR_Result2 , FR_Big
253      nop.i 0
257 //   Detect masked underflow - Tiny + Inexact Only
259 {    .mfi
260      nop.m 999
261 (p6) fcmp.neq.unc.s1 p6, p0 = FR_Result , FR_Result2
262      nop.i 999 
263 };; 
266 //   Is result bigger the allowed range?
267 //   Branch out for underflow
269 {    .mfb
270 (p6) addl            GR_Tag = 147, r0
271 (p8) fcmp.le.unc.s1  p9, p10 = FR_Result2 , FR_NBig
272 (p6) br.cond.spnt    L(LDEXP_UNDERFLOW) 
276 //   Branch out for overflow
278 { .mbb
279      nop.m 0
280 (p7) br.cond.spnt    L(LDEXP_OVERFLOW) 
281 (p9) br.cond.spnt    L(LDEXP_OVERFLOW) 
285 //   Return from main path.
287 {    .mfb
288      nop.m 999
289      nop.f 0
290      br.ret.sptk     b0;;                   
293 .endp ldexp
294 ASM_SIZE_DIRECTIVE(ldexp)
295 .proc __libm_error_region
296 __libm_error_region:
298 L(LDEXP_OVERFLOW): 
299 L(LDEXP_UNDERFLOW): 
302 // Get stack address of N
304 .prologue
305 { .mfi
306     add   GR_Parameter_Y=-32,sp         
307     nop.f 0
308 .save   ar.pfs,GR_SAVE_PFS
309     mov  GR_SAVE_PFS=ar.pfs              
312 // Adjust sp 
314 { .mfi
315 .fframe 64
316    add sp=-64,sp                         
317    nop.f 0
318    mov GR_SAVE_GP=gp       
322 //  Store N on stack in correct position 
323 //  Locate the address of x on stack
325 { .mmi
326    st8 [GR_Parameter_Y] =  GR_N_as_int,16       
327    add GR_Parameter_X = 16,sp          
328 .save   b0, GR_SAVE_B0
329    mov GR_SAVE_B0=b0                  
333 // Store x on the stack.
334 // Get address for result on stack.
336 .body
337 { .mib
338    stfd [GR_Parameter_X] = FR_Norm_X 
339    add   GR_Parameter_RESULT = 0,GR_Parameter_Y   
340    nop.b 0
342 { .mib
343    stfd [GR_Parameter_Y] = FR_Result                 
344    add   GR_Parameter_Y = -16,GR_Parameter_Y
345    br.call.sptk b0=__libm_error_support#   
349 //  Get location of result on stack
351 { .mmi
352    nop.m 0
353    nop.m 0
354    add   GR_Parameter_RESULT = 48,sp    
358 //  Get the new result 
360 { .mmi
361    ldfd  FR_Result = [GR_Parameter_RESULT]      
362 .restore sp
363    add   sp = 64,sp                       
364    mov   b0 = GR_SAVE_B0                  
368 //  Restore gp, ar.pfs and return
370 { .mib
371    mov   gp = GR_SAVE_GP                  
372    mov   ar.pfs = GR_SAVE_PFS             
373    br.ret.sptk     b0                  
376 .endp __libm_error_region
377 ASM_SIZE_DIRECTIVE(__libm_error_region)
379 .type   __libm_error_support#,@function
380 .global __libm_error_support#