OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [gdb/] [doublest.c] - Blame information for rev 1775

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* Floating point routines for GDB, the GNU debugger.
2
   Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
3
   1997, 1998, 1999, 2000, 2001
4
   Free Software Foundation, Inc.
5
 
6
   This file is part of GDB.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 2 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 59 Temple Place - Suite 330,
21
   Boston, MA 02111-1307, USA.  */
22
 
23
/* Support for converting target fp numbers into host DOUBLEST format.  */
24
 
25
/* XXX - This code should really be in libiberty/floatformat.c,
26
   however configuration issues with libiberty made this very
27
   difficult to do in the available time.  */
28
 
29
#include "defs.h"
30
#include "doublest.h"
31
#include "floatformat.h"
32
#include "gdb_assert.h"
33
#include "gdb_string.h"
34
#include "gdbtypes.h"
35
#include <math.h>               /* ldexp */
36
 
37
/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
38
   going to bother with trying to muck around with whether it is defined in
39
   a system header, what we do if not, etc.  */
40
#define FLOATFORMAT_CHAR_BIT 8
41
 
42
static unsigned long get_field (unsigned char *,
43
                                enum floatformat_byteorders,
44
                                unsigned int, unsigned int, unsigned int);
45
 
46
/* Extract a field which starts at START and is LEN bytes long.  DATA and
47
   TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
48
static unsigned long
49
get_field (unsigned char *data, enum floatformat_byteorders order,
50
           unsigned int total_len, unsigned int start, unsigned int len)
51
{
52
  unsigned long result;
53
  unsigned int cur_byte;
54
  int cur_bitshift;
55
 
56
  /* Start at the least significant part of the field.  */
57
  if (order == floatformat_little || order == floatformat_littlebyte_bigword)
58
    {
59
      /* We start counting from the other end (i.e, from the high bytes
60
         rather than the low bytes).  As such, we need to be concerned
61
         with what happens if bit 0 doesn't start on a byte boundary.
62
         I.e, we need to properly handle the case where total_len is
63
         not evenly divisible by 8.  So we compute ``excess'' which
64
         represents the number of bits from the end of our starting
65
         byte needed to get to bit 0. */
66
      int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT);
67
      cur_byte = (total_len / FLOATFORMAT_CHAR_BIT)
68
                 - ((start + len + excess) / FLOATFORMAT_CHAR_BIT);
69
      cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT)
70
                     - FLOATFORMAT_CHAR_BIT;
71
    }
72
  else
73
    {
74
      cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
75
      cur_bitshift =
76
        ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
77
    }
78
  if (cur_bitshift > -FLOATFORMAT_CHAR_BIT)
79
    result = *(data + cur_byte) >> (-cur_bitshift);
80
  else
81
    result = 0;
82
  cur_bitshift += FLOATFORMAT_CHAR_BIT;
83
  if (order == floatformat_little || order == floatformat_littlebyte_bigword)
84
    ++cur_byte;
85
  else
86
    --cur_byte;
87
 
88
  /* Move towards the most significant part of the field.  */
89
  while (cur_bitshift < len)
90
    {
91
      result |= (unsigned long)*(data + cur_byte) << cur_bitshift;
92
      cur_bitshift += FLOATFORMAT_CHAR_BIT;
93
      if (order == floatformat_little || order == floatformat_littlebyte_bigword)
94
        ++cur_byte;
95
      else
96
        --cur_byte;
97
    }
98
  if (len < sizeof(result) * FLOATFORMAT_CHAR_BIT)
99
    /* Mask out bits which are not part of the field */
100
    result &= ((1UL << len) - 1);
101
  return result;
102
}
103
 
104
/* Convert from FMT to a DOUBLEST.
105
   FROM is the address of the extended float.
106
   Store the DOUBLEST in *TO.  */
107
 
108
static void
109
convert_floatformat_to_doublest (const struct floatformat *fmt,
110
                                 const void *from,
111
                                 DOUBLEST *to)
112
{
113
  unsigned char *ufrom = (unsigned char *) from;
114
  DOUBLEST dto;
115
  long exponent;
116
  unsigned long mant;
117
  unsigned int mant_bits, mant_off;
118
  int mant_bits_left;
119
  int special_exponent;         /* It's a NaN, denorm or zero */
120
 
121
  /* If the mantissa bits are not contiguous from one end of the
122
     mantissa to the other, we need to make a private copy of the
123
     source bytes that is in the right order since the unpacking
124
     algorithm assumes that the bits are contiguous.
125
 
126
     Swap the bytes individually rather than accessing them through
127
     "long *" since we have no guarantee that they start on a long
128
     alignment, and also sizeof(long) for the host could be different
129
     than sizeof(long) for the target.  FIXME: Assumes sizeof(long)
130
     for the target is 4. */
131
 
132
  if (fmt->byteorder == floatformat_littlebyte_bigword)
133
    {
134
      static unsigned char *newfrom;
135
      unsigned char *swapin, *swapout;
136
      int longswaps;
137
 
138
      longswaps = fmt->totalsize / FLOATFORMAT_CHAR_BIT;
139
      longswaps >>= 3;
140
 
141
      if (newfrom == NULL)
142
        {
143
          newfrom = (unsigned char *) xmalloc (fmt->totalsize);
144
        }
145
      swapout = newfrom;
146
      swapin = ufrom;
147
      ufrom = newfrom;
148
      while (longswaps-- > 0)
149
        {
150
          /* This is ugly, but efficient */
151
          *swapout++ = swapin[4];
152
          *swapout++ = swapin[5];
153
          *swapout++ = swapin[6];
154
          *swapout++ = swapin[7];
155
          *swapout++ = swapin[0];
156
          *swapout++ = swapin[1];
157
          *swapout++ = swapin[2];
158
          *swapout++ = swapin[3];
159
          swapin += 8;
160
        }
161
    }
162
 
163
  exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
164
                        fmt->exp_start, fmt->exp_len);
165
  /* Note that if exponent indicates a NaN, we can't really do anything useful
166
     (not knowing if the host has NaN's, or how to build one).  So it will
167
     end up as an infinity or something close; that is OK.  */
168
 
169
  mant_bits_left = fmt->man_len;
170
  mant_off = fmt->man_start;
171
  dto = 0.0;
172
 
173
  special_exponent = exponent == 0 || exponent == fmt->exp_nan;
174
 
175
/* Don't bias NaNs. Use minimum exponent for denorms. For simplicity,
176
   we don't check for zero as the exponent doesn't matter. */
177
  if (!special_exponent)
178
    exponent -= fmt->exp_bias;
179
  else if (exponent == 0)
180
    exponent = 1 - fmt->exp_bias;
181
 
182
  /* Build the result algebraically.  Might go infinite, underflow, etc;
183
     who cares. */
184
 
185
/* If this format uses a hidden bit, explicitly add it in now.  Otherwise,
186
   increment the exponent by one to account for the integer bit.  */
187
 
188
  if (!special_exponent)
189
    {
190
      if (fmt->intbit == floatformat_intbit_no)
191
        dto = ldexp (1.0, exponent);
192
      else
193
        exponent++;
194
    }
195
 
196
  while (mant_bits_left > 0)
197
    {
198
      mant_bits = min (mant_bits_left, 32);
199
 
200
      mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
201
                        mant_off, mant_bits);
202
 
203
      dto += ldexp ((double) mant, exponent - mant_bits);
204
      exponent -= mant_bits;
205
      mant_off += mant_bits;
206
      mant_bits_left -= mant_bits;
207
    }
208
 
209
  /* Negate it if negative.  */
210
  if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
211
    dto = -dto;
212
  *to = dto;
213
}
214
 
215
static void put_field (unsigned char *, enum floatformat_byteorders,
216
                       unsigned int,
217
                       unsigned int, unsigned int, unsigned long);
218
 
219
/* Set a field which starts at START and is LEN bytes long.  DATA and
220
   TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER.  */
221
static void
222
put_field (unsigned char *data, enum floatformat_byteorders order,
223
           unsigned int total_len, unsigned int start, unsigned int len,
224
           unsigned long stuff_to_put)
225
{
226
  unsigned int cur_byte;
227
  int cur_bitshift;
228
 
229
  /* Start at the least significant part of the field.  */
230
  if (order == floatformat_little || order == floatformat_littlebyte_bigword)
231
    {
232
      int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT);
233
      cur_byte = (total_len / FLOATFORMAT_CHAR_BIT)
234
                 - ((start + len + excess) / FLOATFORMAT_CHAR_BIT);
235
      cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT)
236
                     - FLOATFORMAT_CHAR_BIT;
237
    }
238
  else
239
    {
240
      cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
241
      cur_bitshift =
242
        ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
243
    }
244
  if (cur_bitshift > -FLOATFORMAT_CHAR_BIT)
245
    {
246
      *(data + cur_byte) &=
247
        ~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1)
248
          << (-cur_bitshift));
249
      *(data + cur_byte) |=
250
        (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift);
251
    }
252
  cur_bitshift += FLOATFORMAT_CHAR_BIT;
253
  if (order == floatformat_little || order == floatformat_littlebyte_bigword)
254
    ++cur_byte;
255
  else
256
    --cur_byte;
257
 
258
  /* Move towards the most significant part of the field.  */
259
  while (cur_bitshift < len)
260
    {
261
      if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT)
262
        {
263
          /* This is the last byte.  */
264
          *(data + cur_byte) &=
265
            ~((1 << (len - cur_bitshift)) - 1);
266
          *(data + cur_byte) |= (stuff_to_put >> cur_bitshift);
267
        }
268
      else
269
        *(data + cur_byte) = ((stuff_to_put >> cur_bitshift)
270
                              & ((1 << FLOATFORMAT_CHAR_BIT) - 1));
271
      cur_bitshift += FLOATFORMAT_CHAR_BIT;
272
      if (order == floatformat_little || order == floatformat_littlebyte_bigword)
273
        ++cur_byte;
274
      else
275
        --cur_byte;
276
    }
277
}
278
 
279
#ifdef HAVE_LONG_DOUBLE
280
/* Return the fractional part of VALUE, and put the exponent of VALUE in *EPTR.
281
   The range of the returned value is >= 0.5 and < 1.0.  This is equivalent to
282
   frexp, but operates on the long double data type.  */
283
 
284
static long double ldfrexp (long double value, int *eptr);
285
 
286
static long double
287
ldfrexp (long double value, int *eptr)
288
{
289
  long double tmp;
290
  int exp;
291
 
292
  /* Unfortunately, there are no portable functions for extracting the exponent
293
     of a long double, so we have to do it iteratively by multiplying or dividing
294
     by two until the fraction is between 0.5 and 1.0.  */
295
 
296
  if (value < 0.0l)
297
    value = -value;
298
 
299
  tmp = 1.0l;
300
  exp = 0;
301
 
302
  if (value >= tmp)             /* Value >= 1.0 */
303
    while (value >= tmp)
304
      {
305
        tmp *= 2.0l;
306
        exp++;
307
      }
308
  else if (value != 0.0l)       /* Value < 1.0  and > 0.0 */
309
    {
310
      while (value < tmp)
311
        {
312
          tmp /= 2.0l;
313
          exp--;
314
        }
315
      tmp *= 2.0l;
316
      exp++;
317
    }
318
 
319
  *eptr = exp;
320
  return value / tmp;
321
}
322
#endif /* HAVE_LONG_DOUBLE */
323
 
324
 
325
/* The converse: convert the DOUBLEST *FROM to an extended float
326
   and store where TO points.  Neither FROM nor TO have any alignment
327
   restrictions.  */
328
 
329
static void
330
convert_doublest_to_floatformat (CONST struct floatformat *fmt,
331
                                 const DOUBLEST *from,
332
                                 void *to)
333
{
334
  DOUBLEST dfrom;
335
  int exponent;
336
  DOUBLEST mant;
337
  unsigned int mant_bits, mant_off;
338
  int mant_bits_left;
339
  unsigned char *uto = (unsigned char *) to;
340
 
341
  memcpy (&dfrom, from, sizeof (dfrom));
342
  memset (uto, 0, (fmt->totalsize + FLOATFORMAT_CHAR_BIT - 1)
343
                    / FLOATFORMAT_CHAR_BIT);
344
  if (dfrom == 0)
345
    return;                     /* Result is zero */
346
  if (dfrom != dfrom)           /* Result is NaN */
347
    {
348
      /* From is NaN */
349
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
350
                 fmt->exp_len, fmt->exp_nan);
351
      /* Be sure it's not infinity, but NaN value is irrel */
352
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
353
                 32, 1);
354
      return;
355
    }
356
 
357
  /* If negative, set the sign bit.  */
358
  if (dfrom < 0)
359
    {
360
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
361
      dfrom = -dfrom;
362
    }
363
 
364
  if (dfrom + dfrom == dfrom && dfrom != 0.0)   /* Result is Infinity */
365
    {
366
      /* Infinity exponent is same as NaN's.  */
367
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
368
                 fmt->exp_len, fmt->exp_nan);
369
      /* Infinity mantissa is all zeroes.  */
370
      put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
371
                 fmt->man_len, 0);
372
      return;
373
    }
374
 
375
#ifdef HAVE_LONG_DOUBLE
376
  mant = ldfrexp (dfrom, &exponent);
377
#else
378
  mant = frexp (dfrom, &exponent);
379
#endif
380
 
381
  put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len,
382
             exponent + fmt->exp_bias - 1);
383
 
384
  mant_bits_left = fmt->man_len;
385
  mant_off = fmt->man_start;
386
  while (mant_bits_left > 0)
387
    {
388
      unsigned long mant_long;
389
      mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
390
 
391
      mant *= 4294967296.0;
392
      mant_long = ((unsigned long) mant) & 0xffffffffL;
393
      mant -= mant_long;
394
 
395
      /* If the integer bit is implicit, then we need to discard it.
396
         If we are discarding a zero, we should be (but are not) creating
397
         a denormalized number which means adjusting the exponent
398
         (I think).  */
399
      if (mant_bits_left == fmt->man_len
400
          && fmt->intbit == floatformat_intbit_no)
401
        {
402
          mant_long <<= 1;
403
          mant_long &= 0xffffffffL;
404
          mant_bits -= 1;
405
        }
406
 
407
      if (mant_bits < 32)
408
        {
409
          /* The bits we want are in the most significant MANT_BITS bits of
410
             mant_long.  Move them to the least significant.  */
411
          mant_long >>= 32 - mant_bits;
412
        }
413
 
414
      put_field (uto, fmt->byteorder, fmt->totalsize,
415
                 mant_off, mant_bits, mant_long);
416
      mant_off += mant_bits;
417
      mant_bits_left -= mant_bits;
418
    }
419
  if (fmt->byteorder == floatformat_littlebyte_bigword)
420
    {
421
      int count;
422
      unsigned char *swaplow = uto;
423
      unsigned char *swaphigh = uto + 4;
424
      unsigned char tmp;
425
 
426
      for (count = 0; count < 4; count++)
427
        {
428
          tmp = *swaplow;
429
          *swaplow++ = *swaphigh;
430
          *swaphigh++ = tmp;
431
        }
432
    }
433
}
434
 
435
/* Check if VAL (which is assumed to be a floating point number whose
436
   format is described by FMT) is negative.  */
437
 
438
int
439
floatformat_is_negative (const struct floatformat *fmt, char *val)
440
{
441
  unsigned char *uval = (unsigned char *) val;
442
  gdb_assert (fmt != NULL);
443
  return get_field (uval, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1);
444
}
445
 
446
/* Check if VAL is "not a number" (NaN) for FMT.  */
447
 
448
int
449
floatformat_is_nan (const struct floatformat *fmt, char *val)
450
{
451
  unsigned char *uval = (unsigned char *) val;
452
  long exponent;
453
  unsigned long mant;
454
  unsigned int mant_bits, mant_off;
455
  int mant_bits_left;
456
 
457
  gdb_assert (fmt != NULL);
458
 
459
  if (! fmt->exp_nan)
460
    return 0;
461
 
462
  exponent = get_field (uval, fmt->byteorder, fmt->totalsize,
463
                        fmt->exp_start, fmt->exp_len);
464
 
465
  if (exponent != fmt->exp_nan)
466
    return 0;
467
 
468
  mant_bits_left = fmt->man_len;
469
  mant_off = fmt->man_start;
470
 
471
  while (mant_bits_left > 0)
472
    {
473
      mant_bits = min (mant_bits_left, 32);
474
 
475
      mant = get_field (uval, fmt->byteorder, fmt->totalsize,
476
                        mant_off, mant_bits);
477
 
478
      /* If there is an explicit integer bit, mask it off.  */
479
      if (mant_off == fmt->man_start
480
          && fmt->intbit == floatformat_intbit_yes)
481
        mant &= ~(1 << (mant_bits - 1));
482
 
483
      if (mant)
484
        return 1;
485
 
486
      mant_off += mant_bits;
487
      mant_bits_left -= mant_bits;
488
    }
489
 
490
  return 0;
491
}
492
 
493
/* Convert the mantissa of VAL (which is assumed to be a floating
494
   point number whose format is described by FMT) into a hexadecimal
495
   and store it in a static string.  Return a pointer to that string.  */
496
 
497
char *
498
floatformat_mantissa (const struct floatformat *fmt, char *val)
499
{
500
  unsigned char *uval = (unsigned char *) val;
501
  unsigned long mant;
502
  unsigned int mant_bits, mant_off;
503
  int mant_bits_left;
504
  static char res[50];
505
  char buf[9];
506
 
507
  /* Make sure we have enough room to store the mantissa.  */
508
  gdb_assert (fmt != NULL);
509
  gdb_assert (sizeof res > ((fmt->man_len + 7) / 8) * 2);
510
 
511
  mant_off = fmt->man_start;
512
  mant_bits_left = fmt->man_len;
513
  mant_bits = (mant_bits_left % 32) > 0 ? mant_bits_left % 32 : 32;
514
 
515
  mant = get_field (uval, fmt->byteorder, fmt->totalsize,
516
                    mant_off, mant_bits);
517
 
518
  sprintf (res, "%lx", mant);
519
 
520
  mant_off += mant_bits;
521
  mant_bits_left -= mant_bits;
522
 
523
  while (mant_bits_left > 0)
524
    {
525
      mant = get_field (uval, fmt->byteorder, fmt->totalsize,
526
                        mant_off, 32);
527
 
528
      sprintf (buf, "%08lx", mant);
529
      strcat (res, buf);
530
 
531
      mant_off += 32;
532
      mant_bits_left -= 32;
533
    }
534
 
535
  return res;
536
}
537
 
538
 
539
/* Convert TO/FROM target to the hosts DOUBLEST floating-point format.
540
 
541
   If the host and target formats agree, we just copy the raw data
542
   into the appropriate type of variable and return, letting the host
543
   increase precision as necessary.  Otherwise, we call the conversion
544
   routine and let it do the dirty work.  */
545
 
546
#ifndef HOST_FLOAT_FORMAT
547
#define HOST_FLOAT_FORMAT 0
548
#endif
549
#ifndef HOST_DOUBLE_FORMAT
550
#define HOST_DOUBLE_FORMAT 0
551
#endif
552
#ifndef HOST_LONG_DOUBLE_FORMAT
553
#define HOST_LONG_DOUBLE_FORMAT 0
554
#endif
555
 
556
static const struct floatformat *host_float_format = HOST_FLOAT_FORMAT;
557
static const struct floatformat *host_double_format = HOST_DOUBLE_FORMAT;
558
static const struct floatformat *host_long_double_format = HOST_LONG_DOUBLE_FORMAT;
559
 
560
void
561
floatformat_to_doublest (const struct floatformat *fmt,
562
                         const void *in, DOUBLEST *out)
563
{
564
  gdb_assert (fmt != NULL);
565
  if (fmt == host_float_format)
566
    {
567
      float val;
568
      memcpy (&val, in, sizeof (val));
569
      *out = val;
570
    }
571
  else if (fmt == host_double_format)
572
    {
573
      double val;
574
      memcpy (&val, in, sizeof (val));
575
      *out = val;
576
    }
577
  else if (fmt == host_long_double_format)
578
    {
579
      long double val;
580
      memcpy (&val, in, sizeof (val));
581
      *out = val;
582
    }
583
  else
584
    convert_floatformat_to_doublest (fmt, in, out);
585
}
586
 
587
void
588
floatformat_from_doublest (const struct floatformat *fmt,
589
                           const DOUBLEST *in, void *out)
590
{
591
  gdb_assert (fmt != NULL);
592
  if (fmt == host_float_format)
593
    {
594
      float val = *in;
595
      memcpy (out, &val, sizeof (val));
596
    }
597
  else if (fmt == host_double_format)
598
    {
599
      double val = *in;
600
      memcpy (out, &val, sizeof (val));
601
    }
602
  else if (fmt == host_long_double_format)
603
    {
604
      long double val = *in;
605
      memcpy (out, &val, sizeof (val));
606
    }
607
  else
608
    convert_doublest_to_floatformat (fmt, in, out);
609
}
610
 
611
 
612
/* Return a floating-point format for a floating-point variable of
613
   length LEN.  Return NULL, if no suitable floating-point format
614
   could be found.
615
 
616
   We need this functionality since information about the
617
   floating-point format of a type is not always available to GDB; the
618
   debug information typically only tells us the size of a
619
   floating-point type.
620
 
621
   FIXME: kettenis/2001-10-28: In many places, particularly in
622
   target-dependent code, the format of floating-point types is known,
623
   but not passed on by GDB.  This should be fixed.  */
624
 
625
const struct floatformat *
626
floatformat_from_length (int len)
627
{
628
  if (len * TARGET_CHAR_BIT == TARGET_FLOAT_BIT)
629
    return TARGET_FLOAT_FORMAT;
630
  else if (len * TARGET_CHAR_BIT == TARGET_DOUBLE_BIT)
631
    return TARGET_DOUBLE_FORMAT;
632
  else if (len * TARGET_CHAR_BIT == TARGET_LONG_DOUBLE_BIT)
633
    return TARGET_LONG_DOUBLE_FORMAT;
634
 
635
  return NULL;
636
}
637
 
638
const struct floatformat *
639
floatformat_from_type (const struct type *type)
640
{
641
  gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
642
  if (TYPE_FLOATFORMAT (type) != NULL)
643
    return TYPE_FLOATFORMAT (type);
644
  else
645
    return floatformat_from_length (TYPE_LENGTH (type));
646
}
647
 
648
/* If the host doesn't define NAN, use zero instead.  */
649
#ifndef NAN
650
#define NAN 0.0
651
#endif
652
 
653
/* Extract a floating-point number of length LEN from a target-order
654
   byte-stream at ADDR.  Returns the value as type DOUBLEST.  */
655
 
656
DOUBLEST
657
extract_floating (const void *addr, int len)
658
{
659
  const struct floatformat *fmt = floatformat_from_length (len);
660
  DOUBLEST val;
661
 
662
  if (fmt == NULL)
663
    {
664
      warning ("Can't store a floating-point number of %d bytes.", len);
665
      return NAN;
666
    }
667
 
668
  floatformat_to_doublest (fmt, addr, &val);
669
  return val;
670
}
671
 
672
/* Store VAL as a floating-point number of length LEN to a
673
   target-order byte-stream at ADDR.  */
674
 
675
void
676
store_floating (void *addr, int len, DOUBLEST val)
677
{
678
  const struct floatformat *fmt = floatformat_from_length (len);
679
 
680
  if (fmt == NULL)
681
    {
682
      warning ("Can't store a floating-point number of %d bytes.", len);
683
      memset (addr, 0, len);
684
      return;
685
    }
686
 
687
  floatformat_from_doublest (fmt, &val, addr);
688
}
689
 
690
/* Extract a floating-point number of type TYPE from a target-order
691
   byte-stream at ADDR.  Returns the value as type DOUBLEST.  */
692
 
693
DOUBLEST
694
extract_typed_floating (const void *addr, const struct type *type)
695
{
696
  DOUBLEST retval;
697
 
698
  gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
699
 
700
  if (TYPE_FLOATFORMAT (type) == NULL)
701
    return extract_floating (addr, TYPE_LENGTH (type));
702
 
703
  floatformat_to_doublest (TYPE_FLOATFORMAT (type), addr, &retval);
704
  return retval;
705
}
706
 
707
/* Store VAL as a floating-point number of type TYPE to a target-order
708
   byte-stream at ADDR.  */
709
 
710
void
711
store_typed_floating (void *addr, const struct type *type, DOUBLEST val)
712
{
713
  gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
714
 
715
  /* FIXME: kettenis/2001-10-28: It is debatable whether we should
716
     zero out any remaining bytes in the target buffer when TYPE is
717
     longer than the actual underlying floating-point format.  Perhaps
718
     we should store a fixed bitpattern in those remaining bytes,
719
     instead of zero, or perhaps we shouldn't touch those remaining
720
     bytes at all.
721
 
722
     NOTE: cagney/2001-10-28: With the way things currently work, it
723
     isn't a good idea to leave the end bits undefined.  This is
724
     because GDB writes out the entire sizeof(<floating>) bits of the
725
     floating-point type even though the value might only be stored
726
     in, and the target processor may only refer to, the first N <
727
     TYPE_LENGTH (type) bits.  If the end of the buffer wasn't
728
     initialized, GDB would write undefined data to the target.  An
729
     errant program, refering to that undefined data, would then
730
     become non-deterministic.
731
 
732
     See also the function convert_typed_floating below.  */
733
  memset (addr, 0, TYPE_LENGTH (type));
734
 
735
  if (TYPE_FLOATFORMAT (type) == NULL)
736
    store_floating (addr, TYPE_LENGTH (type), val);
737
  else
738
    floatformat_from_doublest (TYPE_FLOATFORMAT (type), &val, addr);
739
}
740
 
741
/* Convert a floating-point number of type FROM_TYPE from a
742
   target-order byte-stream at FROM to a floating-point number of type
743
   TO_TYPE, and store it to a target-order byte-stream at TO.  */
744
 
745
void
746
convert_typed_floating (const void *from, const struct type *from_type,
747
                        void *to, const struct type *to_type)
748
{
749
  const struct floatformat *from_fmt = floatformat_from_type (from_type);
750
  const struct floatformat *to_fmt = floatformat_from_type (to_type);
751
 
752
  gdb_assert (TYPE_CODE (from_type) == TYPE_CODE_FLT);
753
  gdb_assert (TYPE_CODE (to_type) == TYPE_CODE_FLT);
754
 
755
  if (from_fmt == NULL || to_fmt == NULL)
756
    {
757
      /* If we don't know the floating-point format of FROM_TYPE or
758
         TO_TYPE, there's not much we can do.  We might make the
759
         assumption that if the length of FROM_TYPE and TO_TYPE match,
760
         their floating-point format would match too, but that
761
         assumption might be wrong on targets that support
762
         floating-point types that only differ in endianness for
763
         example.  So we warn instead, and zero out the target buffer.  */
764
      warning ("Can't convert floating-point number to desired type.");
765
      memset (to, 0, TYPE_LENGTH (to_type));
766
    }
767
  else if (from_fmt == to_fmt)
768
    {
769
      /* We're in business.  The floating-point format of FROM_TYPE
770
         and TO_TYPE match.  However, even though the floating-point
771
         format matches, the length of the type might still be
772
         different.  Make sure we don't overrun any buffers.  See
773
         comment in store_typed_floating for a discussion about
774
         zeroing out remaining bytes in the target buffer.  */
775
      memset (to, 0, TYPE_LENGTH (to_type));
776
      memcpy (to, from, min (TYPE_LENGTH (from_type), TYPE_LENGTH (to_type)));
777
    }
778
  else
779
    {
780
      /* The floating-point types don't match.  The best we can do
781
         (aport from simulating the target FPU) is converting to the
782
         widest floating-point type supported by the host, and then
783
         again to the desired type.  */
784
      DOUBLEST d;
785
 
786
      floatformat_to_doublest (from_fmt, from, &d);
787
      floatformat_from_doublest (to_fmt, &d, to);
788
    }
789
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.