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