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