* doublest.c (FLOATFORMAT_LARGEST_BYTES): New define.
(get_field, put_field): Assert that the format is one we can handle. Simplify logic accordingly. (floatformat_normalize_byteorder): New function. (convert_floatformat_to_doublest): Use floatformat_normalize_byteorder to normalize and select modified byte order. Pass modified byte order to get_field. (floatformat_is_negative, floatformat_is_nan, floatformat_mantissa): Likewise. (convert_doublest_to_floatformat): Select an appropriate intermediate byte order if necessary. Always convert to the final format before returning.
This commit is contained in:
parent
0e1200e593
commit
fcab3fb53b
2 changed files with 146 additions and 80 deletions
|
@ -1,3 +1,18 @@
|
|||
2004-12-05 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
* doublest.c (FLOATFORMAT_LARGEST_BYTES): New define.
|
||||
(get_field, put_field): Assert that the format is one we can handle.
|
||||
Simplify logic accordingly.
|
||||
(floatformat_normalize_byteorder): New function.
|
||||
(convert_floatformat_to_doublest): Use floatformat_normalize_byteorder
|
||||
to normalize and select modified byte order. Pass modified byte order
|
||||
to get_field.
|
||||
(floatformat_is_negative, floatformat_is_nan, floatformat_mantissa):
|
||||
Likewise.
|
||||
(convert_doublest_to_floatformat): Select an appropriate intermediate
|
||||
byte order if necessary. Always convert to the final format before
|
||||
returning.
|
||||
|
||||
2004-12-04 Daniel Jacobowitz <dan@debian.org>
|
||||
|
||||
PR tui/1703
|
||||
|
|
211
gdb/doublest.c
211
gdb/doublest.c
|
@ -40,6 +40,10 @@
|
|||
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);
|
||||
|
@ -54,8 +58,11 @@ get_field (unsigned char *data, enum floatformat_byteorders order,
|
|||
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 || order == floatformat_littlebyte_bigword)
|
||||
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
|
||||
|
@ -81,7 +88,7 @@ get_field (unsigned char *data, enum floatformat_byteorders order,
|
|||
else
|
||||
result = 0;
|
||||
cur_bitshift += FLOATFORMAT_CHAR_BIT;
|
||||
if (order == floatformat_little || order == floatformat_littlebyte_bigword)
|
||||
if (order == floatformat_little)
|
||||
++cur_byte;
|
||||
else
|
||||
--cur_byte;
|
||||
|
@ -99,8 +106,6 @@ get_field (unsigned char *data, enum floatformat_byteorders order,
|
|||
case floatformat_big:
|
||||
--cur_byte;
|
||||
break;
|
||||
case floatformat_littlebyte_bigword:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (len < sizeof(result) * FLOATFORMAT_CHAR_BIT)
|
||||
|
@ -109,6 +114,40 @@ get_field (unsigned char *data, enum floatformat_byteorders order,
|
|||
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. */
|
||||
|
@ -125,51 +164,19 @@ convert_floatformat_to_doublest (const struct floatformat *fmt,
|
|||
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);
|
||||
|
||||
/* 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.
|
||||
order = floatformat_normalize_byteorder (fmt, ufrom, newfrom);
|
||||
|
||||
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 (order != fmt->byteorder)
|
||||
ufrom = newfrom;
|
||||
|
||||
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);
|
||||
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. */
|
||||
|
@ -207,8 +214,7 @@ convert_floatformat_to_doublest (const struct floatformat *fmt,
|
|||
{
|
||||
mant_bits = min (mant_bits_left, 32);
|
||||
|
||||
mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
|
||||
mant_off, mant_bits);
|
||||
mant = get_field (ufrom, order, fmt->totalsize, mant_off, mant_bits);
|
||||
|
||||
dto += ldexp ((double) mant, exponent - mant_bits);
|
||||
exponent -= mant_bits;
|
||||
|
@ -217,7 +223,7 @@ convert_floatformat_to_doublest (const struct floatformat *fmt,
|
|||
}
|
||||
|
||||
/* Negate it if negative. */
|
||||
if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
|
||||
if (get_field (ufrom, order, fmt->totalsize, fmt->sign_start, 1))
|
||||
dto = -dto;
|
||||
*to = dto;
|
||||
}
|
||||
|
@ -236,8 +242,11 @@ put_field (unsigned char *data, enum floatformat_byteorders order,
|
|||
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 || order == floatformat_littlebyte_bigword)
|
||||
if (order == floatformat_little)
|
||||
{
|
||||
int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT);
|
||||
cur_byte = (total_len / FLOATFORMAT_CHAR_BIT)
|
||||
|
@ -260,7 +269,7 @@ put_field (unsigned char *data, enum floatformat_byteorders order,
|
|||
(stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift);
|
||||
}
|
||||
cur_bitshift += FLOATFORMAT_CHAR_BIT;
|
||||
if (order == floatformat_little || order == floatformat_littlebyte_bigword)
|
||||
if (order == floatformat_little)
|
||||
++cur_byte;
|
||||
else
|
||||
--cur_byte;
|
||||
|
@ -279,7 +288,7 @@ put_field (unsigned char *data, enum floatformat_byteorders order,
|
|||
*(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)
|
||||
if (order == floatformat_little)
|
||||
++cur_byte;
|
||||
else
|
||||
--cur_byte;
|
||||
|
@ -347,6 +356,10 @@ convert_doublest_to_floatformat (CONST struct floatformat *fmt,
|
|||
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)
|
||||
|
@ -356,30 +369,30 @@ convert_doublest_to_floatformat (CONST struct floatformat *fmt,
|
|||
if (dfrom != dfrom) /* Result is NaN */
|
||||
{
|
||||
/* From is NaN */
|
||||
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
|
||||
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, fmt->byteorder, fmt->totalsize, fmt->man_start,
|
||||
put_field (uto, order, fmt->totalsize, fmt->man_start,
|
||||
32, 1);
|
||||
return;
|
||||
goto finalize_byteorder;
|
||||
}
|
||||
|
||||
/* If negative, set the sign bit. */
|
||||
if (dfrom < 0)
|
||||
{
|
||||
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
|
||||
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, fmt->byteorder, fmt->totalsize, fmt->exp_start,
|
||||
put_field (uto, order, 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,
|
||||
put_field (uto, order, fmt->totalsize, fmt->man_start,
|
||||
fmt->man_len, 0);
|
||||
return;
|
||||
goto finalize_byteorder;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LONG_DOUBLE
|
||||
|
@ -388,7 +401,7 @@ convert_doublest_to_floatformat (CONST struct floatformat *fmt,
|
|||
mant = frexp (dfrom, &exponent);
|
||||
#endif
|
||||
|
||||
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len,
|
||||
put_field (uto, order, fmt->totalsize, fmt->exp_start, fmt->exp_len,
|
||||
exponent + fmt->exp_bias - 1);
|
||||
|
||||
mant_bits_left = fmt->man_len;
|
||||
|
@ -429,23 +442,31 @@ convert_doublest_to_floatformat (CONST struct floatformat *fmt,
|
|||
mant_long >>= 32 - mant_bits;
|
||||
}
|
||||
|
||||
put_field (uto, fmt->byteorder, fmt->totalsize,
|
||||
put_field (uto, order, fmt->totalsize,
|
||||
mant_off, mant_bits, mant_long);
|
||||
mant_off += mant_bits;
|
||||
mant_bits_left -= mant_bits;
|
||||
}
|
||||
if (fmt->byteorder == floatformat_littlebyte_bigword)
|
||||
|
||||
finalize_byteorder:
|
||||
/* Do we need to byte-swap the words in the result? */
|
||||
if (order != fmt->byteorder)
|
||||
{
|
||||
int count;
|
||||
unsigned char *swaplow = uto;
|
||||
unsigned char *swaphigh = uto + 4;
|
||||
int words;
|
||||
unsigned char *curword = uto;
|
||||
unsigned char tmp;
|
||||
|
||||
for (count = 0; count < 4; count++)
|
||||
words = fmt->totalsize / FLOATFORMAT_CHAR_BIT;
|
||||
words >>= 2;
|
||||
while (words-- > 0)
|
||||
{
|
||||
tmp = *swaplow;
|
||||
*swaplow++ = *swaphigh;
|
||||
*swaphigh++ = tmp;
|
||||
tmp = curword[0];
|
||||
curword[0] = curword[3];
|
||||
curword[3] = tmp;
|
||||
tmp = curword[1];
|
||||
curword[1] = curword[2];
|
||||
curword[2] = tmp;
|
||||
curword += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -457,8 +478,19 @@ int
|
|||
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);
|
||||
return get_field (uval, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1);
|
||||
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. */
|
||||
|
@ -471,14 +503,23 @@ floatformat_is_nan (const struct floatformat *fmt, char *val)
|
|||
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, fmt->byteorder, fmt->totalsize,
|
||||
fmt->exp_start, fmt->exp_len);
|
||||
exponent = get_field (uval, order, fmt->totalsize, fmt->exp_start,
|
||||
fmt->exp_len);
|
||||
|
||||
if (exponent != fmt->exp_nan)
|
||||
return 0;
|
||||
|
@ -490,8 +531,7 @@ floatformat_is_nan (const struct floatformat *fmt, char *val)
|
|||
{
|
||||
mant_bits = min (mant_bits_left, 32);
|
||||
|
||||
mant = get_field (uval, fmt->byteorder, fmt->totalsize,
|
||||
mant_off, mant_bits);
|
||||
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
|
||||
|
@ -521,17 +561,29 @@ floatformat_mantissa (const struct floatformat *fmt, char *val)
|
|||
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 (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);
|
||||
mant = get_field (uval, order, fmt->totalsize, mant_off, mant_bits);
|
||||
|
||||
sprintf (res, "%lx", mant);
|
||||
|
||||
|
@ -540,8 +592,7 @@ floatformat_mantissa (const struct floatformat *fmt, char *val)
|
|||
|
||||
while (mant_bits_left > 0)
|
||||
{
|
||||
mant = get_field (uval, fmt->byteorder, fmt->totalsize,
|
||||
mant_off, 32);
|
||||
mant = get_field (uval, order, fmt->totalsize, mant_off, 32);
|
||||
|
||||
sprintf (buf, "%08lx", mant);
|
||||
strcat (res, buf);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue