1 1.1 christos /* IEEE floating point support routines, for GDB, the GNU Debugger. 2 1.10 christos Copyright (C) 1991-2025 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos This file is part of GDB. 5 1.1 christos 6 1.1 christos This program is free software; you can redistribute it and/or modify 7 1.1 christos it under the terms of the GNU General Public License as published by 8 1.1 christos the Free Software Foundation; either version 2 of the License, or 9 1.1 christos (at your option) any later version. 10 1.1 christos 11 1.1 christos This program is distributed in the hope that it will be useful, 12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 christos GNU General Public License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU General Public License 17 1.1 christos along with this program; if not, write to the Free Software 18 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 19 1.1 christos 20 1.1 christos /* This is needed to pick up the NAN macro on some systems. */ 21 1.3 christos #ifndef _GNU_SOURCE 22 1.1 christos #define _GNU_SOURCE 23 1.3 christos #endif 24 1.1 christos 25 1.1 christos #ifdef HAVE_CONFIG_H 26 1.1 christos #include "config.h" 27 1.1 christos #endif 28 1.1 christos 29 1.1 christos #include <math.h> 30 1.1 christos 31 1.1 christos #ifdef HAVE_STRING_H 32 1.1 christos #include <string.h> 33 1.1 christos #endif 34 1.1 christos 35 1.1 christos /* On some platforms, <float.h> provides DBL_QNAN. */ 36 1.1 christos #ifdef STDC_HEADERS 37 1.1 christos #include <float.h> 38 1.1 christos #endif 39 1.1 christos 40 1.1 christos #include "ansidecl.h" 41 1.1 christos #include "libiberty.h" 42 1.1 christos #include "floatformat.h" 43 1.1 christos 44 1.1 christos #ifndef INFINITY 45 1.1 christos #ifdef HUGE_VAL 46 1.1 christos #define INFINITY HUGE_VAL 47 1.1 christos #else 48 1.1 christos #define INFINITY (1.0 / 0.0) 49 1.1 christos #endif 50 1.1 christos #endif 51 1.1 christos 52 1.1 christos #ifndef NAN 53 1.1 christos #ifdef DBL_QNAN 54 1.1 christos #define NAN DBL_QNAN 55 1.1 christos #else 56 1.1 christos #define NAN (0.0 / 0.0) 57 1.1 christos #endif 58 1.1 christos #endif 59 1.1 christos 60 1.1 christos static int mant_bits_set (const struct floatformat *, const unsigned char *); 61 1.1 christos static unsigned long get_field (const unsigned char *, 62 1.1 christos enum floatformat_byteorders, 63 1.1 christos unsigned int, 64 1.1 christos unsigned int, 65 1.1 christos unsigned int); 66 1.1 christos static int floatformat_always_valid (const struct floatformat *fmt, 67 1.1 christos const void *from); 68 1.1 christos 69 1.1 christos static int 70 1.1 christos floatformat_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED, 71 1.1 christos const void *from ATTRIBUTE_UNUSED) 72 1.1 christos { 73 1.1 christos return 1; 74 1.1 christos } 75 1.1 christos 76 1.1 christos /* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not 77 1.1 christos going to bother with trying to muck around with whether it is defined in 78 1.1 christos a system header, what we do if not, etc. */ 79 1.1 christos #define FLOATFORMAT_CHAR_BIT 8 80 1.1 christos 81 1.8 christos /* floatformats for IEEE half, single, double and quad, big and little endian. */ 82 1.1 christos const struct floatformat floatformat_ieee_half_big = 83 1.1 christos { 84 1.1 christos floatformat_big, 16, 0, 1, 5, 15, 31, 6, 10, 85 1.1 christos floatformat_intbit_no, 86 1.1 christos "floatformat_ieee_half_big", 87 1.1 christos floatformat_always_valid, 88 1.1 christos NULL 89 1.1 christos }; 90 1.1 christos const struct floatformat floatformat_ieee_half_little = 91 1.1 christos { 92 1.1 christos floatformat_little, 16, 0, 1, 5, 15, 31, 6, 10, 93 1.1 christos floatformat_intbit_no, 94 1.1 christos "floatformat_ieee_half_little", 95 1.1 christos floatformat_always_valid, 96 1.1 christos NULL 97 1.1 christos }; 98 1.1 christos const struct floatformat floatformat_ieee_single_big = 99 1.1 christos { 100 1.1 christos floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23, 101 1.1 christos floatformat_intbit_no, 102 1.1 christos "floatformat_ieee_single_big", 103 1.1 christos floatformat_always_valid, 104 1.1 christos NULL 105 1.1 christos }; 106 1.1 christos const struct floatformat floatformat_ieee_single_little = 107 1.1 christos { 108 1.1 christos floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23, 109 1.1 christos floatformat_intbit_no, 110 1.1 christos "floatformat_ieee_single_little", 111 1.1 christos floatformat_always_valid, 112 1.1 christos NULL 113 1.1 christos }; 114 1.1 christos const struct floatformat floatformat_ieee_double_big = 115 1.1 christos { 116 1.1 christos floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52, 117 1.1 christos floatformat_intbit_no, 118 1.1 christos "floatformat_ieee_double_big", 119 1.1 christos floatformat_always_valid, 120 1.1 christos NULL 121 1.1 christos }; 122 1.1 christos const struct floatformat floatformat_ieee_double_little = 123 1.1 christos { 124 1.1 christos floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52, 125 1.1 christos floatformat_intbit_no, 126 1.1 christos "floatformat_ieee_double_little", 127 1.1 christos floatformat_always_valid, 128 1.1 christos NULL 129 1.1 christos }; 130 1.8 christos const struct floatformat floatformat_ieee_quad_big = 131 1.8 christos { 132 1.8 christos floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112, 133 1.8 christos floatformat_intbit_no, 134 1.8 christos "floatformat_ieee_quad_big", 135 1.8 christos floatformat_always_valid, 136 1.8 christos NULL 137 1.8 christos }; 138 1.8 christos const struct floatformat floatformat_ieee_quad_little = 139 1.8 christos { 140 1.8 christos floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112, 141 1.8 christos floatformat_intbit_no, 142 1.8 christos "floatformat_ieee_quad_little", 143 1.8 christos floatformat_always_valid, 144 1.8 christos NULL 145 1.8 christos }; 146 1.1 christos 147 1.1 christos /* floatformat for IEEE double, little endian byte order, with big endian word 148 1.1 christos ordering, as on the ARM. */ 149 1.1 christos 150 1.1 christos const struct floatformat floatformat_ieee_double_littlebyte_bigword = 151 1.1 christos { 152 1.1 christos floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52, 153 1.1 christos floatformat_intbit_no, 154 1.1 christos "floatformat_ieee_double_littlebyte_bigword", 155 1.1 christos floatformat_always_valid, 156 1.1 christos NULL 157 1.1 christos }; 158 1.1 christos 159 1.1 christos /* floatformat for VAX. Not quite IEEE, but close enough. */ 160 1.1 christos 161 1.1 christos const struct floatformat floatformat_vax_f = 162 1.1 christos { 163 1.1 christos floatformat_vax, 32, 0, 1, 8, 129, 0, 9, 23, 164 1.1 christos floatformat_intbit_no, 165 1.1 christos "floatformat_vax_f", 166 1.1 christos floatformat_always_valid, 167 1.1 christos NULL 168 1.1 christos }; 169 1.1 christos const struct floatformat floatformat_vax_d = 170 1.1 christos { 171 1.1 christos floatformat_vax, 64, 0, 1, 8, 129, 0, 9, 55, 172 1.1 christos floatformat_intbit_no, 173 1.1 christos "floatformat_vax_d", 174 1.1 christos floatformat_always_valid, 175 1.1 christos NULL 176 1.1 christos }; 177 1.1 christos const struct floatformat floatformat_vax_g = 178 1.1 christos { 179 1.1 christos floatformat_vax, 64, 0, 1, 11, 1025, 0, 12, 52, 180 1.1 christos floatformat_intbit_no, 181 1.1 christos "floatformat_vax_g", 182 1.1 christos floatformat_always_valid, 183 1.1 christos NULL 184 1.1 christos }; 185 1.1 christos 186 1.1 christos static int floatformat_i387_ext_is_valid (const struct floatformat *fmt, 187 1.1 christos const void *from); 188 1.1 christos 189 1.1 christos static int 190 1.1 christos floatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from) 191 1.1 christos { 192 1.1 christos /* In the i387 double-extended format, if the exponent is all ones, 193 1.1 christos then the integer bit must be set. If the exponent is neither 0 194 1.1 christos nor ~0, the intbit must also be set. Only if the exponent is 195 1.1 christos zero can it be zero, and then it must be zero. */ 196 1.1 christos unsigned long exponent, int_bit; 197 1.1 christos const unsigned char *ufrom = (const unsigned char *) from; 198 1.1 christos 199 1.1 christos exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize, 200 1.1 christos fmt->exp_start, fmt->exp_len); 201 1.1 christos int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize, 202 1.1 christos fmt->man_start, 1); 203 1.1 christos 204 1.1 christos if ((exponent == 0) != (int_bit == 0)) 205 1.1 christos return 0; 206 1.1 christos else 207 1.1 christos return 1; 208 1.1 christos } 209 1.1 christos 210 1.1 christos const struct floatformat floatformat_i387_ext = 211 1.1 christos { 212 1.1 christos floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64, 213 1.1 christos floatformat_intbit_yes, 214 1.1 christos "floatformat_i387_ext", 215 1.1 christos floatformat_i387_ext_is_valid, 216 1.1 christos NULL 217 1.1 christos }; 218 1.1 christos const struct floatformat floatformat_m68881_ext = 219 1.1 christos { 220 1.1 christos /* Note that the bits from 16 to 31 are unused. */ 221 1.1 christos floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64, 222 1.1 christos floatformat_intbit_yes, 223 1.1 christos "floatformat_m68881_ext", 224 1.1 christos floatformat_always_valid, 225 1.1 christos NULL 226 1.1 christos }; 227 1.1 christos const struct floatformat floatformat_i960_ext = 228 1.1 christos { 229 1.1 christos /* Note that the bits from 0 to 15 are unused. */ 230 1.1 christos floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64, 231 1.1 christos floatformat_intbit_yes, 232 1.1 christos "floatformat_i960_ext", 233 1.1 christos floatformat_always_valid, 234 1.1 christos NULL 235 1.1 christos }; 236 1.1 christos const struct floatformat floatformat_m88110_ext = 237 1.1 christos { 238 1.1 christos floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64, 239 1.1 christos floatformat_intbit_yes, 240 1.1 christos "floatformat_m88110_ext", 241 1.1 christos floatformat_always_valid, 242 1.1 christos NULL 243 1.1 christos }; 244 1.1 christos const struct floatformat floatformat_m88110_harris_ext = 245 1.1 christos { 246 1.1 christos /* Harris uses raw format 128 bytes long, but the number is just an ieee 247 1.1 christos double, and the last 64 bits are wasted. */ 248 1.1 christos floatformat_big,128, 0, 1, 11, 0x3ff, 0x7ff, 12, 52, 249 1.1 christos floatformat_intbit_no, 250 1.1 christos "floatformat_m88110_ext_harris", 251 1.1 christos floatformat_always_valid, 252 1.1 christos NULL 253 1.1 christos }; 254 1.1 christos const struct floatformat floatformat_arm_ext_big = 255 1.1 christos { 256 1.1 christos /* Bits 1 to 16 are unused. */ 257 1.1 christos floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64, 258 1.1 christos floatformat_intbit_yes, 259 1.1 christos "floatformat_arm_ext_big", 260 1.1 christos floatformat_always_valid, 261 1.1 christos NULL 262 1.1 christos }; 263 1.1 christos const struct floatformat floatformat_arm_ext_littlebyte_bigword = 264 1.1 christos { 265 1.1 christos /* Bits 1 to 16 are unused. */ 266 1.1 christos floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64, 267 1.1 christos floatformat_intbit_yes, 268 1.1 christos "floatformat_arm_ext_littlebyte_bigword", 269 1.1 christos floatformat_always_valid, 270 1.1 christos NULL 271 1.1 christos }; 272 1.1 christos const struct floatformat floatformat_ia64_spill_big = 273 1.1 christos { 274 1.1 christos floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64, 275 1.1 christos floatformat_intbit_yes, 276 1.1 christos "floatformat_ia64_spill_big", 277 1.1 christos floatformat_always_valid, 278 1.1 christos NULL 279 1.1 christos }; 280 1.1 christos const struct floatformat floatformat_ia64_spill_little = 281 1.1 christos { 282 1.1 christos floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64, 283 1.1 christos floatformat_intbit_yes, 284 1.1 christos "floatformat_ia64_spill_little", 285 1.1 christos floatformat_always_valid, 286 1.1 christos NULL 287 1.1 christos }; 288 1.1 christos 289 1.1 christos static int 290 1.1 christos floatformat_ibm_long_double_is_valid (const struct floatformat *fmt, 291 1.1 christos const void *from) 292 1.1 christos { 293 1.1 christos const unsigned char *ufrom = (const unsigned char *) from; 294 1.1 christos const struct floatformat *hfmt = fmt->split_half; 295 1.1 christos long top_exp, bot_exp; 296 1.1 christos int top_nan = 0; 297 1.1 christos 298 1.1 christos top_exp = get_field (ufrom, hfmt->byteorder, hfmt->totalsize, 299 1.1 christos hfmt->exp_start, hfmt->exp_len); 300 1.1 christos bot_exp = get_field (ufrom + 8, hfmt->byteorder, hfmt->totalsize, 301 1.1 christos hfmt->exp_start, hfmt->exp_len); 302 1.1 christos 303 1.1 christos if ((unsigned long) top_exp == hfmt->exp_nan) 304 1.1 christos top_nan = mant_bits_set (hfmt, ufrom); 305 1.1 christos 306 1.1 christos /* A NaN is valid with any low part. */ 307 1.1 christos if (top_nan) 308 1.1 christos return 1; 309 1.1 christos 310 1.1 christos /* An infinity, zero or denormal requires low part 0 (positive or 311 1.1 christos negative). */ 312 1.1 christos if ((unsigned long) top_exp == hfmt->exp_nan || top_exp == 0) 313 1.1 christos { 314 1.1 christos if (bot_exp != 0) 315 1.1 christos return 0; 316 1.1 christos 317 1.1 christos return !mant_bits_set (hfmt, ufrom + 8); 318 1.1 christos } 319 1.1 christos 320 1.1 christos /* The top part is now a finite normal value. The long double value 321 1.1 christos is the sum of the two parts, and the top part must equal the 322 1.1 christos result of rounding the long double value to nearest double. Thus 323 1.1 christos the bottom part must be <= 0.5ulp of the top part in absolute 324 1.1 christos value, and if it is < 0.5ulp then the long double is definitely 325 1.1 christos valid. */ 326 1.1 christos if (bot_exp < top_exp - 53) 327 1.1 christos return 1; 328 1.1 christos if (bot_exp > top_exp - 53 && bot_exp != 0) 329 1.1 christos return 0; 330 1.1 christos if (bot_exp == 0) 331 1.1 christos { 332 1.1 christos /* The bottom part is 0 or denormal. Determine which, and if 333 1.1 christos denormal the first two set bits. */ 334 1.1 christos int first_bit = -1, second_bit = -1, cur_bit; 335 1.1 christos for (cur_bit = 0; (unsigned int) cur_bit < hfmt->man_len; cur_bit++) 336 1.1 christos if (get_field (ufrom + 8, hfmt->byteorder, hfmt->totalsize, 337 1.1 christos hfmt->man_start + cur_bit, 1)) 338 1.1 christos { 339 1.1 christos if (first_bit == -1) 340 1.1 christos first_bit = cur_bit; 341 1.1 christos else 342 1.1 christos { 343 1.1 christos second_bit = cur_bit; 344 1.1 christos break; 345 1.1 christos } 346 1.1 christos } 347 1.1 christos /* Bottom part 0 is OK. */ 348 1.1 christos if (first_bit == -1) 349 1.1 christos return 1; 350 1.1 christos /* The real exponent of the bottom part is -first_bit. */ 351 1.1 christos if (-first_bit < top_exp - 53) 352 1.1 christos return 1; 353 1.1 christos if (-first_bit > top_exp - 53) 354 1.1 christos return 0; 355 1.1 christos /* The bottom part is at least 0.5ulp of the top part. For this 356 1.1 christos to be OK, the bottom part must be exactly 0.5ulp (i.e. no 357 1.1 christos more bits set) and the top part must have last bit 0. */ 358 1.1 christos if (second_bit != -1) 359 1.1 christos return 0; 360 1.1 christos return !get_field (ufrom, hfmt->byteorder, hfmt->totalsize, 361 1.1 christos hfmt->man_start + hfmt->man_len - 1, 1); 362 1.1 christos } 363 1.1 christos else 364 1.1 christos { 365 1.1 christos /* The bottom part is at least 0.5ulp of the top part. For this 366 1.1 christos to be OK, it must be exactly 0.5ulp (i.e. no explicit bits 367 1.1 christos set) and the top part must have last bit 0. */ 368 1.1 christos if (get_field (ufrom, hfmt->byteorder, hfmt->totalsize, 369 1.1 christos hfmt->man_start + hfmt->man_len - 1, 1)) 370 1.1 christos return 0; 371 1.1 christos return !mant_bits_set (hfmt, ufrom + 8); 372 1.1 christos } 373 1.1 christos } 374 1.1 christos 375 1.3 christos const struct floatformat floatformat_ibm_long_double_big = 376 1.1 christos { 377 1.1 christos floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52, 378 1.1 christos floatformat_intbit_no, 379 1.3 christos "floatformat_ibm_long_double_big", 380 1.1 christos floatformat_ibm_long_double_is_valid, 381 1.1 christos &floatformat_ieee_double_big 382 1.1 christos }; 383 1.3 christos 384 1.3 christos const struct floatformat floatformat_ibm_long_double_little = 385 1.3 christos { 386 1.3 christos floatformat_little, 128, 0, 1, 11, 1023, 2047, 12, 52, 387 1.3 christos floatformat_intbit_no, 388 1.3 christos "floatformat_ibm_long_double_little", 389 1.3 christos floatformat_ibm_long_double_is_valid, 390 1.3 christos &floatformat_ieee_double_little 391 1.3 christos }; 392 1.8 christos 393 1.8 christos const struct floatformat floatformat_bfloat16_big = 394 1.8 christos { 395 1.8 christos floatformat_big, 16, 0, 1, 8, 127, 255, 9, 7, 396 1.8 christos floatformat_intbit_no, 397 1.8 christos "floatformat_bfloat16_big", 398 1.8 christos floatformat_always_valid, 399 1.8 christos NULL 400 1.8 christos }; 401 1.8 christos 402 1.8 christos const struct floatformat floatformat_bfloat16_little = 403 1.8 christos { 404 1.8 christos floatformat_little, 16, 0, 1, 8, 127, 255, 9, 7, 405 1.8 christos floatformat_intbit_no, 406 1.8 christos "floatformat_bfloat16_little", 407 1.8 christos floatformat_always_valid, 408 1.8 christos NULL 409 1.8 christos }; 410 1.1 christos 411 1.1 christos #ifndef min 412 1.1 christos #define min(a, b) ((a) < (b) ? (a) : (b)) 413 1.1 christos #endif 414 1.1 christos 415 1.1 christos /* Return 1 if any bits are explicitly set in the mantissa of UFROM, 416 1.1 christos format FMT, 0 otherwise. */ 417 1.1 christos static int 418 1.1 christos mant_bits_set (const struct floatformat *fmt, const unsigned char *ufrom) 419 1.1 christos { 420 1.1 christos unsigned int mant_bits, mant_off; 421 1.1 christos int mant_bits_left; 422 1.1 christos 423 1.1 christos mant_off = fmt->man_start; 424 1.1 christos mant_bits_left = fmt->man_len; 425 1.1 christos while (mant_bits_left > 0) 426 1.1 christos { 427 1.1 christos mant_bits = min (mant_bits_left, 32); 428 1.1 christos 429 1.1 christos if (get_field (ufrom, fmt->byteorder, fmt->totalsize, 430 1.1 christos mant_off, mant_bits) != 0) 431 1.1 christos return 1; 432 1.1 christos 433 1.1 christos mant_off += mant_bits; 434 1.1 christos mant_bits_left -= mant_bits; 435 1.1 christos } 436 1.1 christos return 0; 437 1.1 christos } 438 1.1 christos 439 1.1 christos /* Extract a field which starts at START and is LEN bits long. DATA and 440 1.1 christos TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ 441 1.1 christos static unsigned long 442 1.1 christos get_field (const unsigned char *data, enum floatformat_byteorders order, 443 1.1 christos unsigned int total_len, unsigned int start, unsigned int len) 444 1.1 christos { 445 1.1 christos unsigned long result = 0; 446 1.1 christos unsigned int cur_byte; 447 1.1 christos int lo_bit, hi_bit, cur_bitshift = 0; 448 1.1 christos int nextbyte = (order == floatformat_little) ? 1 : -1; 449 1.1 christos 450 1.1 christos /* Start is in big-endian bit order! Fix that first. */ 451 1.1 christos start = total_len - (start + len); 452 1.1 christos 453 1.1 christos /* Start at the least significant part of the field. */ 454 1.1 christos if (order == floatformat_little) 455 1.1 christos cur_byte = start / FLOATFORMAT_CHAR_BIT; 456 1.1 christos else 457 1.1 christos cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT; 458 1.1 christos 459 1.1 christos lo_bit = start % FLOATFORMAT_CHAR_BIT; 460 1.1 christos hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT); 461 1.1 christos 462 1.1 christos do 463 1.1 christos { 464 1.1 christos unsigned int shifted = *(data + cur_byte) >> lo_bit; 465 1.1 christos unsigned int bits = hi_bit - lo_bit; 466 1.1 christos unsigned int mask = (1 << bits) - 1; 467 1.1 christos result |= (shifted & mask) << cur_bitshift; 468 1.1 christos len -= bits; 469 1.1 christos cur_bitshift += bits; 470 1.1 christos cur_byte += nextbyte; 471 1.1 christos lo_bit = 0; 472 1.1 christos hi_bit = min (len, FLOATFORMAT_CHAR_BIT); 473 1.1 christos } 474 1.1 christos while (len != 0); 475 1.1 christos 476 1.1 christos return result; 477 1.1 christos } 478 1.1 christos 479 1.1 christos /* Convert from FMT to a double. 480 1.1 christos FROM is the address of the extended float. 481 1.1 christos Store the double in *TO. */ 482 1.1 christos 483 1.1 christos void 484 1.1 christos floatformat_to_double (const struct floatformat *fmt, 485 1.1 christos const void *from, double *to) 486 1.1 christos { 487 1.1 christos const unsigned char *ufrom = (const unsigned char *) from; 488 1.1 christos double dto; 489 1.1 christos long exponent; 490 1.1 christos unsigned long mant; 491 1.1 christos unsigned int mant_bits, mant_off; 492 1.1 christos int mant_bits_left; 493 1.1 christos 494 1.1 christos /* Split values are not handled specially, since the top half has 495 1.1 christos the correctly rounded double value (in the only supported case of 496 1.1 christos split values). */ 497 1.1 christos 498 1.1 christos exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize, 499 1.1 christos fmt->exp_start, fmt->exp_len); 500 1.1 christos 501 1.1 christos /* If the exponent indicates a NaN, we don't have information to 502 1.1 christos decide what to do. So we handle it like IEEE, except that we 503 1.1 christos don't try to preserve the type of NaN. FIXME. */ 504 1.1 christos if ((unsigned long) exponent == fmt->exp_nan) 505 1.1 christos { 506 1.1 christos int nan = mant_bits_set (fmt, ufrom); 507 1.1 christos 508 1.1 christos /* On certain systems (such as GNU/Linux), the use of the 509 1.7 christos INFINITY macro below may generate a warning that cannot be 510 1.1 christos silenced due to a bug in GCC (PR preprocessor/11931). The 511 1.1 christos preprocessor fails to recognise the __extension__ keyword in 512 1.1 christos conjunction with the GNU/C99 extension for hexadecimal 513 1.1 christos floating point constants and will issue a warning when 514 1.1 christos compiling with -pedantic. */ 515 1.1 christos if (nan) 516 1.1 christos dto = NAN; 517 1.1 christos else 518 1.1 christos #ifdef __vax__ 519 1.1 christos dto = HUGE_VAL; 520 1.1 christos #else 521 1.1 christos dto = INFINITY; 522 1.1 christos #endif 523 1.1 christos 524 1.1 christos if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1)) 525 1.1 christos dto = -dto; 526 1.1 christos 527 1.1 christos *to = dto; 528 1.1 christos 529 1.1 christos return; 530 1.1 christos } 531 1.1 christos 532 1.1 christos mant_bits_left = fmt->man_len; 533 1.1 christos mant_off = fmt->man_start; 534 1.1 christos dto = 0.0; 535 1.1 christos 536 1.1 christos /* Build the result algebraically. Might go infinite, underflow, etc; 537 1.1 christos who cares. */ 538 1.1 christos 539 1.3 christos /* For denorms use minimum exponent. */ 540 1.3 christos if (exponent == 0) 541 1.3 christos exponent = 1 - fmt->exp_bias; 542 1.3 christos else 543 1.3 christos { 544 1.3 christos exponent -= fmt->exp_bias; 545 1.3 christos 546 1.3 christos /* If this format uses a hidden bit, explicitly add it in now. 547 1.3 christos Otherwise, increment the exponent by one to account for the 548 1.3 christos integer bit. */ 549 1.1 christos 550 1.1 christos if (fmt->intbit == floatformat_intbit_no) 551 1.1 christos dto = ldexp (1.0, exponent); 552 1.1 christos else 553 1.1 christos exponent++; 554 1.1 christos } 555 1.1 christos 556 1.1 christos while (mant_bits_left > 0) 557 1.1 christos { 558 1.1 christos mant_bits = min (mant_bits_left, 32); 559 1.1 christos 560 1.1 christos mant = get_field (ufrom, fmt->byteorder, fmt->totalsize, 561 1.1 christos mant_off, mant_bits); 562 1.1 christos 563 1.3 christos dto += ldexp ((double) mant, exponent - mant_bits); 564 1.3 christos exponent -= mant_bits; 565 1.1 christos mant_off += mant_bits; 566 1.1 christos mant_bits_left -= mant_bits; 567 1.1 christos } 568 1.1 christos 569 1.1 christos /* Negate it if negative. */ 570 1.1 christos if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1)) 571 1.1 christos dto = -dto; 572 1.1 christos *to = dto; 573 1.1 christos } 574 1.1 christos 575 1.1 christos static void put_field (unsigned char *, enum floatformat_byteorders, 577 1.1 christos unsigned int, 578 1.1 christos unsigned int, 579 1.1 christos unsigned int, 580 1.1 christos unsigned long); 581 1.1 christos 582 1.1 christos /* Set a field which starts at START and is LEN bits long. DATA and 583 1.1 christos TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ 584 1.1 christos static void 585 1.1 christos put_field (unsigned char *data, enum floatformat_byteorders order, 586 1.1 christos unsigned int total_len, unsigned int start, unsigned int len, 587 1.1 christos unsigned long stuff_to_put) 588 1.1 christos { 589 1.1 christos unsigned int cur_byte; 590 1.1 christos int lo_bit, hi_bit; 591 1.1 christos int nextbyte = (order == floatformat_little) ? 1 : -1; 592 1.1 christos 593 1.1 christos /* Start is in big-endian bit order! Fix that first. */ 594 1.1 christos start = total_len - (start + len); 595 1.1 christos 596 1.1 christos /* Start at the least significant part of the field. */ 597 1.1 christos if (order == floatformat_little) 598 1.1 christos cur_byte = start / FLOATFORMAT_CHAR_BIT; 599 1.1 christos else 600 1.1 christos cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT; 601 1.1 christos 602 1.1 christos lo_bit = start % FLOATFORMAT_CHAR_BIT; 603 1.1 christos hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT); 604 1.1 christos 605 1.1 christos do 606 1.1 christos { 607 1.1 christos unsigned char *byte_ptr = data + cur_byte; 608 1.1 christos unsigned int bits = hi_bit - lo_bit; 609 1.1 christos unsigned int mask = ((1 << bits) - 1) << lo_bit; 610 1.1 christos *byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask); 611 1.1 christos stuff_to_put >>= bits; 612 1.1 christos len -= bits; 613 1.1 christos cur_byte += nextbyte; 614 1.1 christos lo_bit = 0; 615 1.1 christos hi_bit = min (len, FLOATFORMAT_CHAR_BIT); 616 1.1 christos } 617 1.1 christos while (len != 0); 618 1.1 christos } 619 1.1 christos 620 1.1 christos /* The converse: convert the double *FROM to an extended float 621 1.1 christos and store where TO points. Neither FROM nor TO have any alignment 622 1.1 christos restrictions. */ 623 1.1 christos 624 1.1 christos void 625 1.1 christos floatformat_from_double (const struct floatformat *fmt, 626 1.1 christos const double *from, void *to) 627 1.1 christos { 628 1.1 christos double dfrom; 629 1.1 christos int exponent; 630 1.1 christos double mant; 631 1.1 christos unsigned int mant_bits, mant_off; 632 1.1 christos int mant_bits_left; 633 1.1 christos unsigned char *uto = (unsigned char *) to; 634 1.1 christos 635 1.1 christos dfrom = *from; 636 1.1 christos memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT); 637 1.1 christos 638 1.1 christos /* Split values are not handled specially, since a bottom half of 639 1.1 christos zero is correct for any value representable as double (in the 640 1.1 christos only supported case of split values). */ 641 1.1 christos 642 1.1 christos /* If negative, set the sign bit. */ 643 1.1 christos if (dfrom < 0) 644 1.1 christos { 645 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1); 646 1.1 christos dfrom = -dfrom; 647 1.1 christos } 648 1.1 christos 649 1.1 christos if (dfrom == 0) 650 1.1 christos { 651 1.1 christos /* 0.0. */ 652 1.1 christos return; 653 1.1 christos } 654 1.1 christos 655 1.1 christos if (dfrom != dfrom) 656 1.1 christos { 657 1.1 christos /* NaN. */ 658 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, 659 1.1 christos fmt->exp_len, fmt->exp_nan); 660 1.1 christos /* Be sure it's not infinity, but NaN value is irrelevant. */ 661 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, 662 1.1 christos 32, 1); 663 1.1 christos return; 664 1.1 christos } 665 1.1 christos 666 1.1 christos if (dfrom + dfrom == dfrom) 667 1.1 christos { 668 1.1 christos /* This can only happen for an infinite value (or zero, which we 669 1.1 christos already handled above). */ 670 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, 671 1.1 christos fmt->exp_len, fmt->exp_nan); 672 1.1 christos return; 673 1.1 christos } 674 1.1 christos 675 1.1 christos mant = frexp (dfrom, &exponent); 676 1.1 christos if (exponent + fmt->exp_bias - 1 > 0) 677 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, 678 1.1 christos fmt->exp_len, exponent + fmt->exp_bias - 1); 679 1.1 christos else 680 1.1 christos { 681 1.1 christos /* Handle a denormalized number. FIXME: What should we do for 682 1.1 christos non-IEEE formats? */ 683 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, 684 1.1 christos fmt->exp_len, 0); 685 1.1 christos mant = ldexp (mant, exponent + fmt->exp_bias - 1); 686 1.1 christos } 687 1.1 christos 688 1.1 christos mant_bits_left = fmt->man_len; 689 1.1 christos mant_off = fmt->man_start; 690 1.1 christos while (mant_bits_left > 0) 691 1.1 christos { 692 1.1 christos unsigned long mant_long; 693 1.1 christos mant_bits = mant_bits_left < 32 ? mant_bits_left : 32; 694 1.1 christos 695 1.1 christos mant *= 4294967296.0; 696 1.1 christos mant_long = (unsigned long)mant; 697 1.1 christos mant -= mant_long; 698 1.1 christos 699 1.1 christos /* If the integer bit is implicit, and we are not creating a 700 1.1 christos denormalized number, then we need to discard it. */ 701 1.1 christos if ((unsigned int) mant_bits_left == fmt->man_len 702 1.1 christos && fmt->intbit == floatformat_intbit_no 703 1.1 christos && exponent + fmt->exp_bias - 1 > 0) 704 1.1 christos { 705 1.1 christos mant_long &= 0x7fffffff; 706 1.1 christos mant_bits -= 1; 707 1.1 christos } 708 1.1 christos else if (mant_bits < 32) 709 1.1 christos { 710 1.1 christos /* The bits we want are in the most significant MANT_BITS bits of 711 1.1 christos mant_long. Move them to the least significant. */ 712 1.1 christos mant_long >>= 32 - mant_bits; 713 1.1 christos } 714 1.1 christos 715 1.1 christos put_field (uto, fmt->byteorder, fmt->totalsize, 716 1.1 christos mant_off, mant_bits, mant_long); 717 1.1 christos mant_off += mant_bits; 718 1.1 christos mant_bits_left -= mant_bits; 719 1.1 christos } 720 1.1 christos } 721 1.1 christos 722 1.1 christos /* Return non-zero iff the data at FROM is a valid number in format FMT. */ 723 1.1 christos 724 1.1 christos int 725 1.1 christos floatformat_is_valid (const struct floatformat *fmt, const void *from) 726 1.1 christos { 727 1.1 christos return fmt->is_valid (fmt, from); 728 1.1 christos } 729 1.1 christos 730 1.1 christos 731 1.1 christos #ifdef IEEE_DEBUG 732 1.1 christos 733 1.1 christos #include <stdio.h> 734 1.1 christos 735 1.1 christos /* This is to be run on a host which uses IEEE floating point. */ 736 1.1 christos 737 1.1 christos void 738 1.1 christos ieee_test (double n) 739 1.1 christos { 740 1.1 christos double result; 741 1.1 christos 742 1.1 christos floatformat_to_double (&floatformat_ieee_double_little, &n, &result); 743 1.1 christos if ((n != result && (! isnan (n) || ! isnan (result))) 744 1.1 christos || (n < 0 && result >= 0) 745 1.1 christos || (n >= 0 && result < 0)) 746 1.1 christos printf ("Differ(to): %.20g -> %.20g\n", n, result); 747 1.1 christos 748 1.1 christos floatformat_from_double (&floatformat_ieee_double_little, &n, &result); 749 1.1 christos if ((n != result && (! isnan (n) || ! isnan (result))) 750 1.1 christos || (n < 0 && result >= 0) 751 1.1 christos || (n >= 0 && result < 0)) 752 1.1 christos printf ("Differ(from): %.20g -> %.20g\n", n, result); 753 1.1 christos 754 1.1 christos #if 0 755 1.1 christos { 756 1.1 christos char exten[16]; 757 1.1 christos 758 1.1 christos floatformat_from_double (&floatformat_m68881_ext, &n, exten); 759 1.1 christos floatformat_to_double (&floatformat_m68881_ext, exten, &result); 760 1.1 christos if (n != result) 761 1.1 christos printf ("Differ(to+from): %.20g -> %.20g\n", n, result); 762 1.1 christos } 763 1.1 christos #endif 764 1.1 christos 765 1.1 christos #if IEEE_DEBUG > 1 766 1.1 christos /* This is to be run on a host which uses 68881 format. */ 767 1.1 christos { 768 1.1 christos long double ex = *(long double *)exten; 769 1.1 christos if (ex != n) 770 1.1 christos printf ("Differ(from vs. extended): %.20g\n", n); 771 1.1 christos } 772 1.1 christos #endif 773 1.1 christos } 774 1.1 christos 775 1.1 christos int 776 1.1 christos main (void) 777 1.1 christos { 778 1.1 christos ieee_test (0.0); 779 1.3 christos ieee_test (0.5); 780 1.1 christos ieee_test (1.1); 781 1.1 christos ieee_test (256.0); 782 1.1 christos ieee_test (0.12345); 783 1.1 christos ieee_test (234235.78907234); 784 1.1 christos ieee_test (-512.0); 785 1.1 christos ieee_test (-0.004321); 786 1.1 christos ieee_test (1.2E-70); 787 1.1 christos ieee_test (1.2E-316); 788 1.1 christos ieee_test (4.9406564584124654E-324); 789 1.1 christos ieee_test (- 4.9406564584124654E-324); 790 1.1 christos ieee_test (- 0.0); 791 1.1 christos ieee_test (- INFINITY); 792 1.1 christos ieee_test (- NAN); 793 1.1 christos ieee_test (INFINITY); 794 1.1 christos ieee_test (NAN); 795 1.1 christos return 0; 796 1.1 christos } 797 #endif 798