0fb4d453882cddad8b993312859bf7299a7f0601
[jlayton/glibc.git] / sysdeps / ia64 / fpu / s_ilogbf.S
1 .file "ilogbf.s"
2
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 // WARRANTY DISCLAIMER
10 // 
11 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
12 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
13 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
14 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
15 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
17 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
18 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
19 // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
20 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
21 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
22 // 
23 // Intel Corporation is the author of this code, and requests that all
24 // problem reports or change requests be submitted to it directly at 
25 // http://developer.intel.com/opensource.
26 //
27 // History
28 //==============================================================
29 // 2/03/00  Initial version
30 // 5/26/00  Fix bug when x a double-extended denormal; 
31 //          if x=0 call error routine, per C9X
32 // 8/15/00  Bundle added after call to __libm_error_support to properly
33 //          set [the previously overwritten] GR_Parameter_RESULT.
34 // 1/20/01  Fixed result for x=0
35
36 .align 32
37 .global ilogbf#
38
39 .section .text
40 .proc  ilogbf#
41 .align 32
42
43 // API
44 //==============================================================
45 // int = ilogbf(float)
46
47 // Overview of operation
48 //==============================================================
49 // ilogbf computes log2(x) as an int
50 // and returns it in r8
51
52 // ilogbf is similar to logbf but differs in the  following ways:
53 //         +-inf
54 //            ilogbf: returns INT_MAX
55 //             logbf: returns +inf
56 //         Nan  returns FP_ILOGBNAN (which is either INT_MAX or INT_MIN)
57 //            ilogbf: returns INT_MAX (7fffffff)
58 //             logbf: returns QNAN (quieted SNAN)
59 //         0    returns FP_ILOGB0 (which is either INT_MIN or -INT_MAX)
60 //            ilogbf: returns INT_MIN (80000000)
61 //             logbf: returns -inf
62
63 // Registers used
64 //==============================================================
65
66 // general local registers: 
67 // ar.pfs r32
68 // r33 -> r37 
69 // r38 -> r41 used as parameters to error path
70
71 // predicate registers used: 
72 // p6 - x nan, inf
73 // p7 - x 0
74 // p8 - x norm, unorm
75 // p9 - x unorm
76
77 // floating-point registers used: 
78 // f8 - f10
79
80 #include "libm_support.h"
81
82 GR_SAVE_PFS         = r32
83 GR_SAVE_B0          = r34
84 GR_SAVE_GP          = r35
85 GR_Parameter_X      = r38
86 GR_Parameter_Y      = r39
87 GR_Parameter_RESULT = r40
88 GR_Parameter_TAG    = r41
89
90 FR_X                = f8
91 FR_Y                = f0
92 FR_RESULT           = f0
93
94
95 ilogbf: 
96
97 // Form signexp of 2^64 in case need to scale denormal
98 { .mmf
99       alloc          r32=ar.pfs,1,5,4,0
100 (p0)  mov      r37 = 0x1003f
101 (p0)  fnorm    f9 = f8 ;;
102 }
103
104 // Form 2^64 in case need to scale denormal
105 { .mfi
106 (p0)  setf.exp f10 = r37
107 (p0)  fclass.m.unc p7, p8 = f8, 0xe3        
108 (p0)  mov      r34 = 0xffff ;;
109 }
110
111 // qnan snan inf norm     unorm 0 -+
112 // 1    1    1   0        0     0 11
113 // e                      3
114 // X ZERO, returns INT_MIN
115 // X INF or NAN, returns INT_MAX
116
117 { .mfi
118 (p0)  mov      r35 = 0x1ffff
119 (p8)    fclass.m.unc p6, p8 = f8, 0x07
120         nop.i 999 ;;
121 }
122 { .mlx
123         nop.m 999
124 (p7)    movl r8 = 0x000000007fffffff ;;       
125 }
126
127 { .mib
128         nop.m 999
129         nop.i 999
130 (p6)    br.cond.spnt  L(ILOGB_ZERO) ;;
131 }
132
133 // Test for denormal
134 { .mfi
135         nop.m 999
136 (p8)    fclass.m.unc p9, p0 = f9, 0x0b        
137         nop.i 999 ;;
138 }
139
140 L(ILOGB_COMMON):
141 // X NORMAL returns true exponent
142 { .mmi
143         nop.m 999 
144 (p8)    getf.exp r33 = f9
145         nop.i 999 ;;
146 }
147
148 // If denormal add 64 to exponent bias for scaling
149 { .mfb
150 (p9)    add     r34 = 64, r34   
151         nop.f 999 
152 (p9)    br.cond.spnt  L(ILOGB_DENORM) ;;
153 }
154
155 { .mmi
156 (p8)    and      r36 = r35, r33
157         nop.m 999
158         nop.i 999 ;;
159 }
160
161 { .mib
162 (p8)    sub r8 = r36, r34                  
163         nop.i 999
164 (p0)    br.ret.sptk    b0 ;;                     
165 }
166
167 L(ILOGB_DENORM):
168 // Here if x denormal
169 // Form x * 2^64 which is normal
170 // Return to common code
171 { .mfb
172         cmp.eq p8,p9 = r0,r0
173         fmpy f9 = f9, f10
174         br.cond.sptk  L(ILOGB_COMMON) ;;
175 }
176
177 // X ZERO
178 // return INT_MIN, call error support
179 L(ILOGB_ZERO): 
180 {.mlx
181       mov            GR_Parameter_TAG = 158
182 (p6)  movl r33 = 0x0000000080000000 ;;
183 };;
184 .endp ilogbf
185 ASM_SIZE_DIRECTIVE(ilogbf)
186
187 .proc __libm_error_region
188 __libm_error_region:
189 .prologue
190 { .mfi
191         add   GR_Parameter_Y=-32,sp             // Parameter 2 value
192         nop.f 0
193 .save   ar.pfs,GR_SAVE_PFS
194         mov  GR_SAVE_PFS=ar.pfs                 // Save ar.pfs
195 }
196 { .mfi
197 .fframe 64
198         add sp=-64,sp                           // Create new stack
199         nop.f 0
200         mov GR_SAVE_GP=gp                       // Save gp
201 };;
202 { .mmi
203         stfs [GR_Parameter_Y] = FR_Y,16         // Save Parameter 2 on stack
204         add GR_Parameter_X = 16,sp              // Parameter 1 address
205 .save   b0, GR_SAVE_B0
206         mov GR_SAVE_B0=b0                       // Save b0
207 };;
208 .body
209 { .mib
210         stfs [GR_Parameter_X] = FR_X            // Store Parameter 1 on stack
211         add   GR_Parameter_RESULT = 0,GR_Parameter_Y
212         nop.b 0                                 // Parameter 3 address
213 }
214 { .mib
215         stfs [GR_Parameter_Y] = FR_RESULT      // Store Parameter 3 on stack
216         add   GR_Parameter_Y = -16,GR_Parameter_Y
217         br.call.sptk b0=__libm_error_support#  // Call error handling function
218 };;
219 { .mmi
220         nop.m 0
221         nop.m 0
222         add   GR_Parameter_RESULT = 48,sp
223 };;
224 { .mmi
225         mov   r8 = r33                         // Store result
226 .restore sp
227         add   sp = 64,sp                       // Restore stack pointer
228         mov   b0 = GR_SAVE_B0                  // Restore return address
229 };;
230 { .mib
231         mov   gp = GR_SAVE_GP                  // Restore gp
232         mov   ar.pfs = GR_SAVE_PFS             // Restore ar.pfs
233         br.ret.sptk     b0                     // Return
234 };;
235
236 .endp __libm_error_region
237 ASM_SIZE_DIRECTIVE(__libm_error_region)
238
239 .type   __libm_error_support#,@function
240 .global __libm_error_support#