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