443ae92a3c426adcc21c6876a5301ee27873c56b
[jlayton/glibc.git] / sysdeps / ia64 / fpu / s_ceill.S
1 .file "ceill.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
28 #include "libm_support.h"
29
30 .align 32
31 .global ceill#
32
33 .section .text
34 .proc  ceill#
35 .align 32
36
37 // History
38 //==============================================================
39 // 2/02/00: Initial version
40 // 6/13/00: Improved speed
41 // 6/27/00: Eliminated incorrect invalid flag setting
42
43 // API
44 //==============================================================
45 // double ceill(double x)
46
47 // general input registers:  
48
49 ceil_GR_FFFF      = r14
50 ceil_GR_signexp   = r15
51 ceil_GR_exponent  = r16
52 ceil_GR_expmask   = r17
53 ceil_GR_bigexp    = r18
54
55
56 // predicate registers used: 
57
58 // p6  ==> Input is NaN, infinity, zero
59 // p7  ==> Input is denormal
60 // p8  ==> Input is <0
61 // p9  ==> Input is >=0
62 // p10 ==> Input is already an integer (bigger than largest integer)
63 // p11 ==> Input is not a large integer
64 // p12 ==> Input is a smaller integer
65 // p13 ==> Input is not an even integer, so inexact must be set
66 // p14 ==> Input is between -1 and 0, so result will be -0 and inexact
67
68
69 // floating-point registers used: 
70
71 CEIL_SIGNED_ZERO  = f7
72 CEIL_NORM_f8      = f9                        
73 CEIL_FFFF         = f10 
74 CEIL_INEXACT      = f11 
75 CEIL_FLOAT_INT_f8 = f12
76 CEIL_INT_f8       = f13
77 CEIL_adj          = f14
78 CEIL_MINUS_ONE    = f15
79
80 // Overview of operation
81 //==============================================================
82
83 // long double ceill(long double x)
84 // Return an integer value (represented as a long double) that is the smallest 
85 // value not less than x
86 // This is x rounded toward +infinity to an integral value.
87 // Inexact is set if x != ceill(x)
88 // **************************************************************************
89
90 // Set denormal flag for denormal input and
91 // and take denormal fault if necessary.
92
93 // Is the input an integer value already?
94
95 // double_extended
96 // if the exponent is > 1003e => 3F(true) = 63(decimal)
97 // we have a significand of 64 bits 1.63-bits.
98 // If we multiply by 2^63, we no longer have a fractional part
99 // So input is an integer value already.
100
101 // double
102 // if the exponent is >= 10033 => 34(true) = 52(decimal)
103 // 34 + 3ff = 433
104 // we have a significand of 53 bits 1.52-bits. (implicit 1)
105 // If we multiply by 2^52, we no longer have a fractional part
106 // So input is an integer value already.
107
108 // single
109 // if the exponent is > 10016 => 17(true) = 23(decimal)
110 // we have a significand of 24 bits 1.23-bits. (implicit 1)
111 // If we multiply by 2^23, we no longer have a fractional part
112 // So input is an integer value already.
113
114 // If x is NAN, ZERO, or INFINITY, then  return
115
116 // qnan snan inf norm     unorm 0 -+
117 // 1    1    1   0        0     1 11     0xe7
118
119
120 ceill:
121
122 { .mfi
123       getf.exp ceil_GR_signexp  = f8
124       fcvt.fx.trunc.s1     CEIL_INT_f8  = f8
125       addl        ceil_GR_bigexp = 0x1003e, r0
126 }
127 { .mfi
128       addl        ceil_GR_FFFF      = -1,r0
129       fcmp.lt.s1  p8,p9 = f8,f0
130       mov         ceil_GR_expmask    = 0x1FFFF ;;
131 }
132
133 // p7 ==> denorm
134 { .mfi
135       setf.sig    CEIL_FFFF  = ceil_GR_FFFF
136       fclass.m    p7,p0 = f8, 0x0b
137       nop.i 999
138 }
139 { .mfi
140       nop.m 999
141       fnorm           CEIL_NORM_f8  = f8
142       nop.i 999 ;;
143 }
144
145 // Form 0 with sign of input in case negative zero is needed
146 { .mfi
147       nop.m 999
148       fmerge.s           CEIL_SIGNED_ZERO = f8, f0
149       nop.i 999
150 }
151 { .mfi
152       nop.m 999
153       fsub.s1           CEIL_MINUS_ONE = f0, f1
154       nop.i 999 ;;
155 }
156
157 // p6 ==> NAN, INF, ZERO
158 { .mfb
159       nop.m 999
160       fclass.m      p6,p10 = f8, 0xe7
161 (p7)  br.cond.spnt  L(CEIL_DENORM) ;;
162 }
163
164 L(CEIL_COMMON):
165 .pred.rel "mutex",p8,p9
166 // Set adjustment to add to trunc(x) for result
167 //   If x>0,  adjustment is 1.0
168 //   If x<=0, adjustment is 0.0
169 { .mfi
170       and      ceil_GR_exponent = ceil_GR_signexp, ceil_GR_expmask
171 (p9)  fadd.s1  CEIL_adj = f1,f0
172       nop.i 999
173 }
174 { .mfi
175       nop.m 999
176 (p8)  fadd.s1  CEIL_adj = f0,f0
177       nop.i 999 ;;
178 }
179
180 { .mfi
181 (p10) cmp.ge.unc    p10,p11 = ceil_GR_exponent, ceil_GR_bigexp
182 (p6)  fnorm   f8 = f8
183       nop.i 999 ;;
184 }
185
186 { .mfi
187       nop.m 999
188 (p11) fcvt.xf         CEIL_FLOAT_INT_f8   = CEIL_INT_f8
189       nop.i 999 ;;
190 }
191
192 { .mfi
193       nop.m 999
194 (p10) fnorm   f8 = CEIL_NORM_f8
195       nop.i 999 ;;
196 }
197
198 // Is -1 < x < 0?  If so, result will be -0.  Special case it with p14 set.
199 { .mfi
200       nop.m 999
201 (p8)  fcmp.gt.unc.s1 p14,p0 = CEIL_NORM_f8, CEIL_MINUS_ONE
202       nop.i 999 ;;
203 }
204
205 { .mfi
206 (p14) cmp.ne  p11,p0 = r0,r0
207 (p14) fnorm   f8 = CEIL_SIGNED_ZERO
208       nop.i 999
209 }
210 { .mfi
211       nop.m 999
212 (p14) fmpy.s0     CEIL_INEXACT = CEIL_FFFF,CEIL_FFFF
213       nop.i 999 ;;
214 }
215
216 { .mfi
217       nop.m 999
218 (p11) fadd     f8 = CEIL_FLOAT_INT_f8,CEIL_adj
219       nop.i 999 ;;
220 }
221 { .mfi
222       nop.m 999
223 (p11) fcmp.eq.unc.s1  p12,p13  = CEIL_FLOAT_INT_f8, CEIL_NORM_f8
224       nop.i 999 ;;
225 }
226
227 // Set inexact if result not equal to input
228 { .mfi
229       nop.m 999
230 (p13) fmpy.s0     CEIL_INEXACT = CEIL_FFFF,CEIL_FFFF
231       nop.i 999
232 }
233 // Set result to input if integer
234 { .mfb
235       nop.m 999
236 (p12) fnorm   f8 = CEIL_NORM_f8
237       br.ret.sptk    b0 ;;
238 }
239
240 // Here if input denorm
241 L(CEIL_DENORM):
242 { .mfb
243       getf.exp ceil_GR_signexp  = CEIL_NORM_f8
244       fcvt.fx.trunc.s1     CEIL_INT_f8  = CEIL_NORM_f8
245       br.cond.sptk  L(CEIL_COMMON) ;;
246 }
247
248 .endp ceill
249 ASM_SIZE_DIRECTIVE(ceill)