1 | /* Helper macros for x86 libm functions. |
2 | Copyright (C) 2015-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #ifndef _I386_MATH_ASM_H |
20 | #define _I386_MATH_ASM_H 1 |
21 | |
22 | /* Remove excess range and precision by storing a value on the stack |
23 | and loading it back. */ |
24 | #define FLT_NARROW_EVAL \ |
25 | subl $4, %esp; \ |
26 | cfi_adjust_cfa_offset (4); \ |
27 | fstps (%esp); \ |
28 | flds (%esp); \ |
29 | addl $4, %esp; \ |
30 | cfi_adjust_cfa_offset (-4); |
31 | #define DBL_NARROW_EVAL \ |
32 | subl $8, %esp; \ |
33 | cfi_adjust_cfa_offset (8); \ |
34 | fstpl (%esp); \ |
35 | fldl (%esp); \ |
36 | addl $8, %esp; \ |
37 | cfi_adjust_cfa_offset (-8); |
38 | |
39 | /* Define constants for the minimum value of a floating-point |
40 | type. */ |
41 | #define DEFINE_FLT_MIN \ |
42 | .section .rodata.cst4,"aM",@progbits,4; \ |
43 | .p2align 2; \ |
44 | .type flt_min,@object; \ |
45 | flt_min: \ |
46 | .byte 0, 0, 0x80, 0; \ |
47 | .size flt_min, .-flt_min; |
48 | #define DEFINE_DBL_MIN \ |
49 | .section .rodata.cst8,"aM",@progbits,8; \ |
50 | .p2align 3; \ |
51 | .type dbl_min,@object; \ |
52 | dbl_min: \ |
53 | .byte 0, 0, 0, 0, 0, 0, 0x10, 0; \ |
54 | .size dbl_min, .-dbl_min; |
55 | #define DEFINE_LDBL_MIN \ |
56 | .section .rodata.cst16,"aM",@progbits,16; \ |
57 | .p2align 4; \ |
58 | .type ldbl_min,@object; \ |
59 | ldbl_min: \ |
60 | .byte 0, 0, 0, 0, 0, 0, 0, 0x80, 0x1, 0; \ |
61 | .byte 0, 0, 0, 0, 0, 0; \ |
62 | .size ldbl_min, .-ldbl_min; |
63 | |
64 | /* Remove excess range and precision by storing a value on the stack |
65 | and loading it back. The value is given to be nonnegative or NaN; |
66 | if it is subnormal, also force an underflow exception. The |
67 | relevant constant for the minimum of the type must have been |
68 | defined, the MO macro must have been defined for access to memory |
69 | operands, and, if PIC, the PIC register must have been loaded. */ |
70 | #define FLT_NARROW_EVAL_UFLOW_NONNEG_NAN \ |
71 | subl $4, %esp; \ |
72 | cfi_adjust_cfa_offset (4); \ |
73 | flds MO(flt_min); \ |
74 | fld %st(1); \ |
75 | fucompp; \ |
76 | fnstsw; \ |
77 | sahf; \ |
78 | jnc 6424f; \ |
79 | fld %st(0); \ |
80 | fmul %st(0); \ |
81 | fstps (%esp); \ |
82 | 6424: fstps (%esp); \ |
83 | flds (%esp); \ |
84 | addl $4, %esp; \ |
85 | cfi_adjust_cfa_offset (-4); |
86 | #define DBL_NARROW_EVAL_UFLOW_NONNEG_NAN \ |
87 | subl $8, %esp; \ |
88 | cfi_adjust_cfa_offset (8); \ |
89 | fldl MO(dbl_min); \ |
90 | fld %st(1); \ |
91 | fucompp; \ |
92 | fnstsw; \ |
93 | sahf; \ |
94 | jnc 6453f; \ |
95 | fld %st(0); \ |
96 | fmul %st(0); \ |
97 | fstpl (%esp); \ |
98 | 6453: fstpl (%esp); \ |
99 | fldl (%esp); \ |
100 | addl $8, %esp; \ |
101 | cfi_adjust_cfa_offset (-8); |
102 | |
103 | /* Likewise, but the argument is not a NaN (so fcom instructions, |
104 | which support memory operands, can be used). */ |
105 | #define FLT_NARROW_EVAL_UFLOW_NONNEG \ |
106 | subl $4, %esp; \ |
107 | cfi_adjust_cfa_offset (4); \ |
108 | fcoms MO(flt_min); \ |
109 | fnstsw; \ |
110 | sahf; \ |
111 | jnc 6424f; \ |
112 | fld %st(0); \ |
113 | fmul %st(0); \ |
114 | fstps (%esp); \ |
115 | 6424: fstps (%esp); \ |
116 | flds (%esp); \ |
117 | addl $4, %esp; \ |
118 | cfi_adjust_cfa_offset (-4); |
119 | #define DBL_NARROW_EVAL_UFLOW_NONNEG \ |
120 | subl $8, %esp; \ |
121 | cfi_adjust_cfa_offset (8); \ |
122 | fcoml MO(dbl_min); \ |
123 | fnstsw; \ |
124 | sahf; \ |
125 | jnc 6453f; \ |
126 | fld %st(0); \ |
127 | fmul %st(0); \ |
128 | fstpl (%esp); \ |
129 | 6453: fstpl (%esp); \ |
130 | fldl (%esp); \ |
131 | addl $8, %esp; \ |
132 | cfi_adjust_cfa_offset (-8); |
133 | |
134 | /* Likewise, but the non-NaN argument may be negative. */ |
135 | #define FLT_NARROW_EVAL_UFLOW_NONNAN \ |
136 | subl $4, %esp; \ |
137 | cfi_adjust_cfa_offset (4); \ |
138 | fld %st(0); \ |
139 | fabs; \ |
140 | fcomps MO(flt_min); \ |
141 | fnstsw; \ |
142 | sahf; \ |
143 | jnc 6424f; \ |
144 | fld %st(0); \ |
145 | fmul %st(0); \ |
146 | fstps (%esp); \ |
147 | 6424: fstps (%esp); \ |
148 | flds (%esp); \ |
149 | addl $4, %esp; \ |
150 | cfi_adjust_cfa_offset (-4); |
151 | #define DBL_NARROW_EVAL_UFLOW_NONNAN \ |
152 | subl $8, %esp; \ |
153 | cfi_adjust_cfa_offset (8); \ |
154 | fld %st(0); \ |
155 | fabs; \ |
156 | fcompl MO(dbl_min); \ |
157 | fnstsw; \ |
158 | sahf; \ |
159 | jnc 6453f; \ |
160 | fld %st(0); \ |
161 | fmul %st(0); \ |
162 | fstpl (%esp); \ |
163 | 6453: fstpl (%esp); \ |
164 | fldl (%esp); \ |
165 | addl $8, %esp; \ |
166 | cfi_adjust_cfa_offset (-8); |
167 | |
168 | /* Force an underflow exception if the given value is subnormal. The |
169 | relevant constant for the minimum of the type must have been |
170 | defined, the MO macro must have been defined for access to memory |
171 | operands, and, if PIC, the PIC register must have been loaded. */ |
172 | #define FLT_CHECK_FORCE_UFLOW \ |
173 | flds MO(flt_min); \ |
174 | fld %st(1); \ |
175 | fabs; \ |
176 | fucompp; \ |
177 | fnstsw; \ |
178 | sahf; \ |
179 | jnc 6424f; \ |
180 | subl $4, %esp; \ |
181 | cfi_adjust_cfa_offset (4); \ |
182 | fld %st(0); \ |
183 | fmul %st(0); \ |
184 | fstps (%esp); \ |
185 | addl $4, %esp; \ |
186 | cfi_adjust_cfa_offset (-4); \ |
187 | 6424: |
188 | #define DBL_CHECK_FORCE_UFLOW \ |
189 | fldl MO(dbl_min); \ |
190 | fld %st(1); \ |
191 | fabs; \ |
192 | fucompp; \ |
193 | fnstsw; \ |
194 | sahf; \ |
195 | jnc 6453f; \ |
196 | subl $8, %esp; \ |
197 | cfi_adjust_cfa_offset (8); \ |
198 | fld %st(0); \ |
199 | fmul %st(0); \ |
200 | fstpl (%esp); \ |
201 | addl $8, %esp; \ |
202 | cfi_adjust_cfa_offset (-8); \ |
203 | 6453: |
204 | |
205 | /* Likewise, but also remove excess range and precision if the value |
206 | is subnormal. */ |
207 | #define FLT_CHECK_FORCE_UFLOW_NARROW \ |
208 | flds MO(flt_min); \ |
209 | fld %st(1); \ |
210 | fabs; \ |
211 | fucompp; \ |
212 | fnstsw; \ |
213 | sahf; \ |
214 | jnc 6424f; \ |
215 | subl $4, %esp; \ |
216 | cfi_adjust_cfa_offset (4); \ |
217 | fld %st(0); \ |
218 | fmul %st(0); \ |
219 | fstps (%esp); \ |
220 | fstps (%esp); \ |
221 | flds (%esp); \ |
222 | addl $4, %esp; \ |
223 | cfi_adjust_cfa_offset (-4); \ |
224 | 6424: |
225 | #define DBL_CHECK_FORCE_UFLOW_NARROW \ |
226 | fldl MO(dbl_min); \ |
227 | fld %st(1); \ |
228 | fabs; \ |
229 | fucompp; \ |
230 | fnstsw; \ |
231 | sahf; \ |
232 | jnc 6453f; \ |
233 | subl $8, %esp; \ |
234 | cfi_adjust_cfa_offset (8); \ |
235 | fld %st(0); \ |
236 | fmul %st(0); \ |
237 | fstpl (%esp); \ |
238 | fstpl (%esp); \ |
239 | fldl (%esp); \ |
240 | addl $8, %esp; \ |
241 | cfi_adjust_cfa_offset (-8); \ |
242 | 6453: |
243 | |
244 | /* Likewise, but the argument is nonnegative or NaN. */ |
245 | #define LDBL_CHECK_FORCE_UFLOW_NONNEG_NAN \ |
246 | fldt MO(ldbl_min); \ |
247 | fld %st(1); \ |
248 | fucompp; \ |
249 | fnstsw; \ |
250 | sahf; \ |
251 | jnc 6464f; \ |
252 | fld %st(0); \ |
253 | fmul %st(0); \ |
254 | fstp %st(0); \ |
255 | 6464: |
256 | |
257 | /* Likewise, but the argument is not a NaN. */ |
258 | #define FLT_CHECK_FORCE_UFLOW_NONNAN \ |
259 | fld %st(0); \ |
260 | fabs; \ |
261 | fcomps MO(flt_min); \ |
262 | fnstsw; \ |
263 | sahf; \ |
264 | jnc 6424f; \ |
265 | subl $4, %esp; \ |
266 | cfi_adjust_cfa_offset (4); \ |
267 | fld %st(0); \ |
268 | fmul %st(0); \ |
269 | fstps (%esp); \ |
270 | addl $4, %esp; \ |
271 | cfi_adjust_cfa_offset (-4); \ |
272 | 6424: |
273 | #define DBL_CHECK_FORCE_UFLOW_NONNAN \ |
274 | fld %st(0); \ |
275 | fabs; \ |
276 | fcompl MO(dbl_min); \ |
277 | fnstsw; \ |
278 | sahf; \ |
279 | jnc 6453f; \ |
280 | subl $8, %esp; \ |
281 | cfi_adjust_cfa_offset (8); \ |
282 | fld %st(0); \ |
283 | fmul %st(0); \ |
284 | fstpl (%esp); \ |
285 | addl $8, %esp; \ |
286 | cfi_adjust_cfa_offset (-8); \ |
287 | 6453: |
288 | #define LDBL_CHECK_FORCE_UFLOW_NONNAN \ |
289 | fldt MO(ldbl_min); \ |
290 | fld %st(1); \ |
291 | fabs; \ |
292 | fcompp; \ |
293 | fnstsw; \ |
294 | sahf; \ |
295 | jnc 6464f; \ |
296 | fld %st(0); \ |
297 | fmul %st(0); \ |
298 | fstp %st(0); \ |
299 | 6464: |
300 | |
301 | /* Likewise, but the argument is nonnegative and not a NaN. */ |
302 | #define FLT_CHECK_FORCE_UFLOW_NONNEG \ |
303 | fcoms MO(flt_min); \ |
304 | fnstsw; \ |
305 | sahf; \ |
306 | jnc 6424f; \ |
307 | subl $4, %esp; \ |
308 | cfi_adjust_cfa_offset (4); \ |
309 | fld %st(0); \ |
310 | fmul %st(0); \ |
311 | fstps (%esp); \ |
312 | addl $4, %esp; \ |
313 | cfi_adjust_cfa_offset (-4); \ |
314 | 6424: |
315 | #define DBL_CHECK_FORCE_UFLOW_NONNEG \ |
316 | fcoml MO(dbl_min); \ |
317 | fnstsw; \ |
318 | sahf; \ |
319 | jnc 6453f; \ |
320 | subl $8, %esp; \ |
321 | cfi_adjust_cfa_offset (8); \ |
322 | fld %st(0); \ |
323 | fmul %st(0); \ |
324 | fstpl (%esp); \ |
325 | addl $8, %esp; \ |
326 | cfi_adjust_cfa_offset (-8); \ |
327 | 6453: |
328 | #define LDBL_CHECK_FORCE_UFLOW_NONNEG \ |
329 | fldt MO(ldbl_min); \ |
330 | fld %st(1); \ |
331 | fcompp; \ |
332 | fnstsw; \ |
333 | sahf; \ |
334 | jnc 6464f; \ |
335 | fld %st(0); \ |
336 | fmul %st(0); \ |
337 | fstp %st(0); \ |
338 | 6464: |
339 | |
340 | #endif /* i386-math-asm.h. */ |
341 | |