@ -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 .
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 ;
order = floatformat_normalize_byteorder ( fmt , ufrom , newfrom ) ;
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 ;
}
}
if ( order ! = fmt - > byteorder )
ufrom = newfrom ;
exponent = get_field ( ufrom , fmt - > byte order, 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 - > byte order, 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 - > byte order, 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 - > byte order, 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 - > byte order, 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 - > byte order, 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 - > byte order, 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 - > byte order, 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 - > byte order, 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 ) ;