Index: doublest.c =================================================================== RCS file: /cvs/src/src/gdb/doublest.c,v retrieving revision 1.22 diff -p -p -r1.22 doublest.c *** doublest.c 24 Aug 2004 22:49:27 -0000 1.22 --- doublest.c 4 Dec 2004 23:42:51 -0000 *************** *** 40,45 **** --- 40,49 ---- a system header, what we do if not, etc. */ #define FLOATFORMAT_CHAR_BIT 8 + /* The number of bytes that the largest floating-point type that we + can convert to doublest will need. */ + #define FLOATFORMAT_LARGEST_BYTES 16 + static unsigned long get_field (unsigned char *, enum floatformat_byteorders, unsigned int, unsigned int, unsigned int); *************** get_field (unsigned char *data, enum flo *** 54,61 **** unsigned int cur_byte; int cur_bitshift; /* Start at the least significant part of the field. */ ! if (order == floatformat_little || order == floatformat_littlebyte_bigword) { /* We start counting from the other end (i.e, from the high bytes rather than the low bytes). As such, we need to be concerned --- 58,68 ---- unsigned int cur_byte; int cur_bitshift; + /* Caller must byte-swap words before calling this routine. */ + gdb_assert (order == floatformat_little || order == floatformat_big); + /* Start at the least significant part of the field. */ ! if (order == floatformat_little) { /* We start counting from the other end (i.e, from the high bytes rather than the low bytes). As such, we need to be concerned *************** get_field (unsigned char *data, enum flo *** 81,87 **** else result = 0; cur_bitshift += FLOATFORMAT_CHAR_BIT; ! if (order == floatformat_little || order == floatformat_littlebyte_bigword) ++cur_byte; else --cur_byte; --- 88,94 ---- else result = 0; cur_bitshift += FLOATFORMAT_CHAR_BIT; ! if (order == floatformat_little) ++cur_byte; else --cur_byte; *************** get_field (unsigned char *data, enum flo *** 99,106 **** case floatformat_big: --cur_byte; break; - case floatformat_littlebyte_bigword: - break; } } if (len < sizeof(result) * FLOATFORMAT_CHAR_BIT) --- 106,111 ---- *************** get_field (unsigned char *data, enum flo *** 109,114 **** --- 114,153 ---- return result; } + /* Normalize the byte order of FROM into TO. If no normalization is needed + then FMT->byteorder is returned and TO is not changed; otherwise the format + of the normalized form in TO is returned. */ + static enum floatformat_byteorders + floatformat_normalize_byteorder (const struct floatformat *fmt, + const void *from, void *to) + { + const unsigned char *swapin; + unsigned char *swapout; + int words; + + if (fmt->byteorder == floatformat_little + || fmt->byteorder == floatformat_big) + return fmt->byteorder; + + gdb_assert (fmt->byteorder == floatformat_littlebyte_bigword); + + words = fmt->totalsize / FLOATFORMAT_CHAR_BIT; + words >>= 2; + + swapout = (unsigned char *)to; + swapin = (const unsigned char *)from; + + while (words-- > 0) + { + *swapout++ = swapin[3]; + *swapout++ = swapin[2]; + *swapout++ = swapin[1]; + *swapout++ = swapin[0]; + swapin += 4; + } + return floatformat_big; + } + /* Convert from FMT to a DOUBLEST. FROM is the address of the extended float. Store the DOUBLEST in *TO. */ *************** convert_floatformat_to_doublest (const s *** 125,175 **** unsigned int mant_bits, mant_off; int mant_bits_left; int special_exponent; /* It's a NaN, denorm or zero */ ! /* If the mantissa bits are not contiguous from one end of the ! mantissa to the other, we need to make a private copy of the ! source bytes that is in the right order since the unpacking ! algorithm assumes that the bits are contiguous. ! ! Swap the bytes individually rather than accessing them through ! "long *" since we have no guarantee that they start on a long ! alignment, and also sizeof(long) for the host could be different ! than sizeof(long) for the target. FIXME: Assumes sizeof(long) ! for the target is 4. */ ! ! if (fmt->byteorder == floatformat_littlebyte_bigword) ! { ! static unsigned char *newfrom; ! unsigned char *swapin, *swapout; ! int longswaps; ! ! longswaps = fmt->totalsize / FLOATFORMAT_CHAR_BIT; ! longswaps >>= 3; ! if (newfrom == NULL) ! { ! newfrom = (unsigned char *) xmalloc (fmt->totalsize); ! } ! swapout = newfrom; ! swapin = ufrom; ! ufrom = newfrom; ! while (longswaps-- > 0) ! { ! /* This is ugly, but efficient */ ! *swapout++ = swapin[4]; ! *swapout++ = swapin[5]; ! *swapout++ = swapin[6]; ! *swapout++ = swapin[7]; ! *swapout++ = swapin[0]; ! *swapout++ = swapin[1]; ! *swapout++ = swapin[2]; ! *swapout++ = swapin[3]; ! swapin += 8; ! } ! } ! exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize, ! fmt->exp_start, fmt->exp_len); /* Note that if exponent indicates a NaN, we can't really do anything useful (not knowing if the host has NaN's, or how to build one). So it will end up as an infinity or something close; that is OK. */ --- 164,182 ---- unsigned int mant_bits, mant_off; int mant_bits_left; int special_exponent; /* It's a NaN, denorm or zero */ + enum floatformat_byteorders order; + unsigned char newfrom[FLOATFORMAT_LARGEST_BYTES]; + + gdb_assert (fmt->totalsize + <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT); ! order = floatformat_normalize_byteorder (fmt, ufrom, newfrom); ! if (order != fmt->byteorder) ! ufrom = newfrom; ! exponent = get_field (ufrom, order, fmt->totalsize, fmt->exp_start, ! fmt->exp_len); /* Note that if exponent indicates a NaN, we can't really do anything useful (not knowing if the host has NaN's, or how to build one). So it will end up as an infinity or something close; that is OK. */ *************** convert_floatformat_to_doublest (const s *** 207,214 **** { mant_bits = min (mant_bits_left, 32); ! mant = get_field (ufrom, fmt->byteorder, fmt->totalsize, ! mant_off, mant_bits); dto += ldexp ((double) mant, exponent - mant_bits); exponent -= mant_bits; --- 214,220 ---- { mant_bits = min (mant_bits_left, 32); ! mant = get_field (ufrom, order, fmt->totalsize, mant_off, mant_bits); dto += ldexp ((double) mant, exponent - mant_bits); exponent -= mant_bits; *************** convert_floatformat_to_doublest (const s *** 217,223 **** } /* Negate it if negative. */ ! if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1)) dto = -dto; *to = dto; } --- 223,229 ---- } /* Negate it if negative. */ ! if (get_field (ufrom, order, fmt->totalsize, fmt->sign_start, 1)) dto = -dto; *to = dto; } *************** put_field (unsigned char *data, enum flo *** 236,243 **** unsigned int cur_byte; int cur_bitshift; /* Start at the least significant part of the field. */ ! if (order == floatformat_little || order == floatformat_littlebyte_bigword) { int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT); cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) --- 242,252 ---- unsigned int cur_byte; int cur_bitshift; + /* Caller must byte-swap words before calling this routine. */ + gdb_assert (order == floatformat_little || order == floatformat_big); + /* Start at the least significant part of the field. */ ! if (order == floatformat_little) { int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT); cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) *************** put_field (unsigned char *data, enum flo *** 260,266 **** (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift); } cur_bitshift += FLOATFORMAT_CHAR_BIT; ! if (order == floatformat_little || order == floatformat_littlebyte_bigword) ++cur_byte; else --cur_byte; --- 269,275 ---- (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift); } cur_bitshift += FLOATFORMAT_CHAR_BIT; ! if (order == floatformat_little) ++cur_byte; else --cur_byte; *************** put_field (unsigned char *data, enum flo *** 279,285 **** *(data + cur_byte) = ((stuff_to_put >> cur_bitshift) & ((1 << FLOATFORMAT_CHAR_BIT) - 1)); cur_bitshift += FLOATFORMAT_CHAR_BIT; ! if (order == floatformat_little || order == floatformat_littlebyte_bigword) ++cur_byte; else --cur_byte; --- 288,294 ---- *(data + cur_byte) = ((stuff_to_put >> cur_bitshift) & ((1 << FLOATFORMAT_CHAR_BIT) - 1)); cur_bitshift += FLOATFORMAT_CHAR_BIT; ! if (order == floatformat_little) ++cur_byte; else --cur_byte; *************** convert_doublest_to_floatformat (CONST s *** 347,352 **** --- 356,365 ---- unsigned int mant_bits, mant_off; int mant_bits_left; unsigned char *uto = (unsigned char *) to; + enum floatformat_byteorders order = fmt->byteorder; + + if (order == floatformat_littlebyte_bigword) + order = floatformat_big; memcpy (&dfrom, from, sizeof (dfrom)); memset (uto, 0, (fmt->totalsize + FLOATFORMAT_CHAR_BIT - 1) *************** convert_doublest_to_floatformat (CONST s *** 356,385 **** if (dfrom != dfrom) /* Result is NaN */ { /* From is NaN */ ! put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len, fmt->exp_nan); /* Be sure it's not infinity, but NaN value is irrel */ ! put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, 32, 1); ! return; } /* If negative, set the sign bit. */ if (dfrom < 0) { ! put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1); dfrom = -dfrom; } if (dfrom + dfrom == dfrom && dfrom != 0.0) /* Result is Infinity */ { /* Infinity exponent is same as NaN's. */ ! put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len, fmt->exp_nan); /* Infinity mantissa is all zeroes. */ ! put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, fmt->man_len, 0); ! return; } #ifdef HAVE_LONG_DOUBLE --- 369,398 ---- if (dfrom != dfrom) /* Result is NaN */ { /* From is NaN */ ! put_field (uto, order, fmt->totalsize, fmt->exp_start, fmt->exp_len, fmt->exp_nan); /* Be sure it's not infinity, but NaN value is irrel */ ! put_field (uto, order, fmt->totalsize, fmt->man_start, 32, 1); ! goto finalize_byteorder; } /* If negative, set the sign bit. */ if (dfrom < 0) { ! put_field (uto, order, fmt->totalsize, fmt->sign_start, 1, 1); dfrom = -dfrom; } if (dfrom + dfrom == dfrom && dfrom != 0.0) /* Result is Infinity */ { /* Infinity exponent is same as NaN's. */ ! put_field (uto, order, fmt->totalsize, fmt->exp_start, fmt->exp_len, fmt->exp_nan); /* Infinity mantissa is all zeroes. */ ! put_field (uto, order, fmt->totalsize, fmt->man_start, fmt->man_len, 0); ! goto finalize_byteorder; } #ifdef HAVE_LONG_DOUBLE *************** convert_doublest_to_floatformat (CONST s *** 388,394 **** mant = frexp (dfrom, &exponent); #endif ! put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len, exponent + fmt->exp_bias - 1); mant_bits_left = fmt->man_len; --- 401,407 ---- mant = frexp (dfrom, &exponent); #endif ! put_field (uto, order, fmt->totalsize, fmt->exp_start, fmt->exp_len, exponent + fmt->exp_bias - 1); mant_bits_left = fmt->man_len; *************** convert_doublest_to_floatformat (CONST s *** 429,451 **** mant_long >>= 32 - mant_bits; } ! put_field (uto, fmt->byteorder, fmt->totalsize, mant_off, mant_bits, mant_long); mant_off += mant_bits; mant_bits_left -= mant_bits; } ! if (fmt->byteorder == floatformat_littlebyte_bigword) { ! int count; ! unsigned char *swaplow = uto; ! unsigned char *swaphigh = uto + 4; unsigned char tmp; ! for (count = 0; count < 4; count++) { ! tmp = *swaplow; ! *swaplow++ = *swaphigh; ! *swaphigh++ = tmp; } } } --- 442,472 ---- mant_long >>= 32 - mant_bits; } ! put_field (uto, order, fmt->totalsize, mant_off, mant_bits, mant_long); mant_off += mant_bits; mant_bits_left -= mant_bits; } ! ! finalize_byteorder: ! /* Do we need to byte-swap the words in the result? */ ! if (order != fmt->byteorder) { ! int words; ! unsigned char *curword = uto; unsigned char tmp; ! words = fmt->totalsize / FLOATFORMAT_CHAR_BIT; ! words >>= 2; ! while (words-- > 0) { ! tmp = curword[0]; ! curword[0] = curword[3]; ! curword[3] = tmp; ! tmp = curword[1]; ! curword[1] = curword[2]; ! curword[2] = tmp; ! curword += 4; } } } *************** int *** 457,464 **** floatformat_is_negative (const struct floatformat *fmt, char *val) { unsigned char *uval = (unsigned char *) val; gdb_assert (fmt != NULL); ! return get_field (uval, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1); } /* Check if VAL is "not a number" (NaN) for FMT. */ --- 478,496 ---- floatformat_is_negative (const struct floatformat *fmt, char *val) { unsigned char *uval = (unsigned char *) val; + enum floatformat_byteorders order; + unsigned char newfrom[FLOATFORMAT_LARGEST_BYTES]; + gdb_assert (fmt != NULL); ! gdb_assert (fmt->totalsize ! <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT); ! ! order = floatformat_normalize_byteorder (fmt, uval, newfrom); ! ! if (order != fmt->byteorder) ! uval = newfrom; ! ! return get_field (uval, order, fmt->totalsize, fmt->sign_start, 1); } /* Check if VAL is "not a number" (NaN) for FMT. */ *************** floatformat_is_nan (const struct floatfo *** 471,484 **** unsigned long mant; unsigned int mant_bits, mant_off; int mant_bits_left; ! gdb_assert (fmt != NULL); if (! fmt->exp_nan) return 0; ! exponent = get_field (uval, fmt->byteorder, fmt->totalsize, ! fmt->exp_start, fmt->exp_len); if (exponent != fmt->exp_nan) return 0; --- 503,525 ---- unsigned long mant; unsigned int mant_bits, mant_off; int mant_bits_left; ! enum floatformat_byteorders order; ! unsigned char newfrom[FLOATFORMAT_LARGEST_BYTES]; ! gdb_assert (fmt != NULL); + gdb_assert (fmt->totalsize + <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT); + + order = floatformat_normalize_byteorder (fmt, uval, newfrom); + + if (order != fmt->byteorder) + uval = newfrom; if (! fmt->exp_nan) return 0; ! exponent = get_field (uval, order, fmt->totalsize, fmt->exp_start, ! fmt->exp_len); if (exponent != fmt->exp_nan) return 0; *************** floatformat_is_nan (const struct floatfo *** 490,497 **** { mant_bits = min (mant_bits_left, 32); ! mant = get_field (uval, fmt->byteorder, fmt->totalsize, ! mant_off, mant_bits); /* If there is an explicit integer bit, mask it off. */ if (mant_off == fmt->man_start --- 531,537 ---- { mant_bits = min (mant_bits_left, 32); ! mant = get_field (uval, order, fmt->totalsize, mant_off, mant_bits); /* If there is an explicit integer bit, mask it off. */ if (mant_off == fmt->man_start *************** floatformat_mantissa (const struct float *** 521,537 **** int mant_bits_left; static char res[50]; char buf[9]; /* Make sure we have enough room to store the mantissa. */ - gdb_assert (fmt != NULL); gdb_assert (sizeof res > ((fmt->man_len + 7) / 8) * 2); mant_off = fmt->man_start; mant_bits_left = fmt->man_len; mant_bits = (mant_bits_left % 32) > 0 ? mant_bits_left % 32 : 32; ! mant = get_field (uval, fmt->byteorder, fmt->totalsize, ! mant_off, mant_bits); sprintf (res, "%lx", mant); --- 561,589 ---- int mant_bits_left; static char res[50]; char buf[9]; + enum floatformat_byteorders order; + unsigned char newfrom[FLOATFORMAT_LARGEST_BYTES]; + + gdb_assert (fmt != NULL); + gdb_assert (fmt->totalsize + <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT); + + order = floatformat_normalize_byteorder (fmt, uval, newfrom); + + if (order != fmt->byteorder) + uval = newfrom; + + if (! fmt->exp_nan) + return 0; /* Make sure we have enough room to store the mantissa. */ gdb_assert (sizeof res > ((fmt->man_len + 7) / 8) * 2); mant_off = fmt->man_start; mant_bits_left = fmt->man_len; mant_bits = (mant_bits_left % 32) > 0 ? mant_bits_left % 32 : 32; ! mant = get_field (uval, order, fmt->totalsize, mant_off, mant_bits); sprintf (res, "%lx", mant); *************** floatformat_mantissa (const struct float *** 540,547 **** while (mant_bits_left > 0) { ! mant = get_field (uval, fmt->byteorder, fmt->totalsize, ! mant_off, 32); sprintf (buf, "%08lx", mant); strcat (res, buf); --- 592,598 ---- while (mant_bits_left > 0) { ! mant = get_field (uval, order, fmt->totalsize, mant_off, 32); sprintf (buf, "%08lx", mant); strcat (res, buf);