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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [gdb/] [dfp.c] - Blame information for rev 311

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

Line No. Rev Author Line
1 227 jeremybenn
/* Decimal floating point support for GDB.
2
 
3
   Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
 
20
#include "defs.h"
21
#include "expression.h"
22
#include "gdbtypes.h"
23
#include "value.h"
24
#include "dfp.h"
25
 
26
/* The order of the following headers is important for making sure
27
   decNumber structure is large enough to hold decimal128 digits.  */
28
 
29
#include "dpd/decimal128.h"
30
#include "dpd/decimal64.h"
31
#include "dpd/decimal32.h"
32
 
33
/* In GDB, we are using an array of gdb_byte to represent decimal values.
34
   They are stored in host byte order.  This routine does the conversion if
35
   the target byte order is different.  */
36
static void
37
match_endianness (const gdb_byte *from, int len, enum bfd_endian byte_order,
38
                  gdb_byte *to)
39
{
40
  int i;
41
 
42
#if WORDS_BIGENDIAN
43
#define OPPOSITE_BYTE_ORDER BFD_ENDIAN_LITTLE
44
#else
45
#define OPPOSITE_BYTE_ORDER BFD_ENDIAN_BIG
46
#endif
47
 
48
  if (byte_order == OPPOSITE_BYTE_ORDER)
49
    for (i = 0; i < len; i++)
50
      to[i] = from[len - i - 1];
51
  else
52
    for (i = 0; i < len; i++)
53
      to[i] = from[i];
54
 
55
  return;
56
}
57
 
58
/* Helper function to get the appropriate libdecnumber context for each size
59
   of decimal float.  */
60
static void
61
set_decnumber_context (decContext *ctx, int len)
62
{
63
  switch (len)
64
    {
65
      case 4:
66
        decContextDefault (ctx, DEC_INIT_DECIMAL32);
67
        break;
68
      case 8:
69
        decContextDefault (ctx, DEC_INIT_DECIMAL64);
70
        break;
71
      case 16:
72
        decContextDefault (ctx, DEC_INIT_DECIMAL128);
73
        break;
74
    }
75
 
76
  ctx->traps = 0;
77
}
78
 
79
/* Check for errors signaled in the decimal context structure.  */
80
static void
81
decimal_check_errors (decContext *ctx)
82
{
83
  /* An error here could be a division by zero, an overflow, an underflow or
84
     an invalid operation (from the DEC_Errors constant in decContext.h).
85
     Since GDB doesn't complain about division by zero, overflow or underflow
86
     errors for binary floating, we won't complain about them for decimal
87
     floating either.  */
88
  if (ctx->status & DEC_IEEE_854_Invalid_operation)
89
    {
90
      /* Leave only the error bits in the status flags.  */
91
      ctx->status &= DEC_IEEE_854_Invalid_operation;
92
      error (_("Cannot perform operation: %s"), decContextStatusToString (ctx));
93
    }
94
}
95
 
96
/* Helper function to convert from libdecnumber's appropriate representation
97
   for computation to each size of decimal float.  */
98
static void
99
decimal_from_number (const decNumber *from, gdb_byte *to, int len)
100
{
101
  decContext set;
102
 
103
  set_decnumber_context (&set, len);
104
 
105
  switch (len)
106
    {
107
      case 4:
108
        decimal32FromNumber ((decimal32 *) to, from, &set);
109
        break;
110
      case 8:
111
        decimal64FromNumber ((decimal64 *) to, from, &set);
112
        break;
113
      case 16:
114
        decimal128FromNumber ((decimal128 *) to, from, &set);
115
        break;
116
    }
117
}
118
 
119
/* Helper function to convert each size of decimal float to libdecnumber's
120
   appropriate representation for computation.  */
121
static void
122
decimal_to_number (const gdb_byte *from, int len, decNumber *to)
123
{
124
  switch (len)
125
    {
126
      case 4:
127
        decimal32ToNumber ((decimal32 *) from, to);
128
        break;
129
      case 8:
130
        decimal64ToNumber ((decimal64 *) from, to);
131
        break;
132
      case 16:
133
        decimal128ToNumber ((decimal128 *) from, to);
134
        break;
135
      default:
136
        error (_("Unknown decimal floating point type.\n"));
137
        break;
138
    }
139
}
140
 
141
/* Convert decimal type to its string representation.  LEN is the length
142
   of the decimal type, 4 bytes for decimal32, 8 bytes for decimal64 and
143
   16 bytes for decimal128.  */
144
void
145
decimal_to_string (const gdb_byte *decbytes, int len,
146
                   enum bfd_endian byte_order, char *s)
147
{
148
  gdb_byte dec[16];
149
 
150
  match_endianness (decbytes, len, byte_order, dec);
151
 
152
  switch (len)
153
    {
154
      case 4:
155
        decimal32ToString ((decimal32 *) dec, s);
156
        break;
157
      case 8:
158
        decimal64ToString ((decimal64 *) dec, s);
159
        break;
160
      case 16:
161
        decimal128ToString ((decimal128 *) dec, s);
162
        break;
163
      default:
164
        error (_("Unknown decimal floating point type."));
165
        break;
166
    }
167
}
168
 
169
/* Convert the string form of a decimal value to its decimal representation.
170
   LEN is the length of the decimal type, 4 bytes for decimal32, 8 bytes for
171
   decimal64 and 16 bytes for decimal128.  */
172
int
173
decimal_from_string (gdb_byte *decbytes, int len, enum bfd_endian byte_order,
174
                     const char *string)
175
{
176
  decContext set;
177
  gdb_byte dec[16];
178
 
179
  set_decnumber_context (&set, len);
180
 
181
  switch (len)
182
    {
183
      case 4:
184
        decimal32FromString ((decimal32 *) dec, string, &set);
185
        break;
186
      case 8:
187
        decimal64FromString ((decimal64 *) dec, string, &set);
188
        break;
189
      case 16:
190
        decimal128FromString ((decimal128 *) dec, string, &set);
191
        break;
192
      default:
193
        error (_("Unknown decimal floating point type."));
194
        break;
195
    }
196
 
197
  match_endianness (dec, len, byte_order, decbytes);
198
 
199
  /* Check for errors in the DFP operation.  */
200
  decimal_check_errors (&set);
201
 
202
  return 1;
203
}
204
 
205
/* Converts a value of an integral type to a decimal float of
206
   specified LEN bytes.  */
207
void
208
decimal_from_integral (struct value *from,
209
                       gdb_byte *to, int len, enum bfd_endian byte_order)
210
{
211
  LONGEST l;
212
  gdb_byte dec[16];
213
  decNumber number;
214
  struct type *type;
215
 
216
  type = check_typedef (value_type (from));
217
 
218
  if (TYPE_LENGTH (type) > 4)
219
    /* libdecnumber can convert only 32-bit integers.  */
220
    error (_("Conversion of large integer to a decimal floating type is not supported."));
221
 
222
  l = value_as_long (from);
223
 
224
  if (TYPE_UNSIGNED (type))
225
    decNumberFromUInt32 (&number, (unsigned int) l);
226
  else
227
    decNumberFromInt32 (&number, (int) l);
228
 
229
  decimal_from_number (&number, dec, len);
230
  match_endianness (dec, len, byte_order, to);
231
}
232
 
233
/* Converts a value of a float type to a decimal float of
234
   specified LEN bytes.
235
 
236
   This is an ugly way to do the conversion, but libdecnumber does
237
   not offer a direct way to do it.  */
238
void
239
decimal_from_floating (struct value *from,
240
                       gdb_byte *to, int len, enum bfd_endian byte_order)
241
{
242
  char *buffer;
243
 
244
  buffer = xstrprintf ("%.30" DOUBLEST_PRINT_FORMAT, value_as_double (from));
245
 
246
  decimal_from_string (to, len, byte_order, buffer);
247
 
248
  xfree (buffer);
249
}
250
 
251
/* Converts a decimal float of LEN bytes to a double value.  */
252
DOUBLEST
253
decimal_to_doublest (const gdb_byte *from, int len, enum bfd_endian byte_order)
254
{
255
  char buffer[MAX_DECIMAL_STRING];
256
 
257
  /* This is an ugly way to do the conversion, but libdecnumber does
258
     not offer a direct way to do it.  */
259
  decimal_to_string (from, len, byte_order, buffer);
260
  return strtod (buffer, NULL);
261
}
262
 
263
/* Perform operation OP with operands X and Y with sizes LEN_X and LEN_Y
264
   and byte orders BYTE_ORDER_X and BYTE_ORDER_Y, and store value in
265
   RESULT with size LEN_RESULT and byte order BYTE_ORDER_RESULT.  */
266
void
267
decimal_binop (enum exp_opcode op,
268
               const gdb_byte *x, int len_x, enum bfd_endian byte_order_x,
269
               const gdb_byte *y, int len_y, enum bfd_endian byte_order_y,
270
               gdb_byte *result, int len_result,
271
               enum bfd_endian byte_order_result)
272
{
273
  decContext set;
274
  decNumber number1, number2, number3;
275
  gdb_byte dec1[16], dec2[16], dec3[16];
276
 
277
  match_endianness (x, len_x, byte_order_x, dec1);
278
  match_endianness (y, len_y, byte_order_y, dec2);
279
 
280
  decimal_to_number (dec1, len_x, &number1);
281
  decimal_to_number (dec2, len_y, &number2);
282
 
283
  set_decnumber_context (&set, len_result);
284
 
285
  switch (op)
286
    {
287
      case BINOP_ADD:
288
        decNumberAdd (&number3, &number1, &number2, &set);
289
        break;
290
      case BINOP_SUB:
291
        decNumberSubtract (&number3, &number1, &number2, &set);
292
        break;
293
      case BINOP_MUL:
294
        decNumberMultiply (&number3, &number1, &number2, &set);
295
        break;
296
      case BINOP_DIV:
297
        decNumberDivide (&number3, &number1, &number2, &set);
298
        break;
299
      case BINOP_EXP:
300
        decNumberPower (&number3, &number1, &number2, &set);
301
        break;
302
      default:
303
        internal_error (__FILE__, __LINE__,
304
                        _("Unknown decimal floating point operation."));
305
        break;
306
    }
307
 
308
  /* Check for errors in the DFP operation.  */
309
  decimal_check_errors (&set);
310
 
311
  decimal_from_number (&number3, dec3, len_result);
312
 
313
  match_endianness (dec3, len_result, byte_order_result, result);
314
}
315
 
316
/* Returns true if X (which is LEN bytes wide) is the number zero.  */
317
int
318
decimal_is_zero (const gdb_byte *x, int len, enum bfd_endian byte_order)
319
{
320
  decNumber number;
321
  gdb_byte dec[16];
322
 
323
  match_endianness (x, len, byte_order, dec);
324
  decimal_to_number (dec, len, &number);
325
 
326
  return decNumberIsZero (&number);
327
}
328
 
329
/* Compares two numbers numerically.  If X is less than Y then the return value
330
   will be -1.  If they are equal, then the return value will be 0.  If X is
331
   greater than the Y then the return value will be 1.  */
332
int
333
decimal_compare (const gdb_byte *x, int len_x, enum bfd_endian byte_order_x,
334
                 const gdb_byte *y, int len_y, enum bfd_endian byte_order_y)
335
{
336
  decNumber number1, number2, result;
337
  decContext set;
338
  gdb_byte dec1[16], dec2[16];
339
  int len_result;
340
 
341
  match_endianness (x, len_x, byte_order_x, dec1);
342
  match_endianness (y, len_y, byte_order_y, dec2);
343
 
344
  decimal_to_number (dec1, len_x, &number1);
345
  decimal_to_number (dec2, len_y, &number2);
346
 
347
  /* Perform the comparison in the larger of the two sizes.  */
348
  len_result = len_x > len_y ? len_x : len_y;
349
  set_decnumber_context (&set, len_result);
350
 
351
  decNumberCompare (&result, &number1, &number2, &set);
352
 
353
  /* Check for errors in the DFP operation.  */
354
  decimal_check_errors (&set);
355
 
356
  if (decNumberIsNaN (&result))
357
    error (_("Comparison with an invalid number (NaN)."));
358
  else if (decNumberIsZero (&result))
359
    return 0;
360
  else if (decNumberIsNegative (&result))
361
    return -1;
362
  else
363
    return 1;
364
}
365
 
366
/* Convert a decimal value from a decimal type with LEN_FROM bytes to a
367
   decimal type with LEN_TO bytes.  */
368
void
369
decimal_convert (const gdb_byte *from, int len_from,
370
                 enum bfd_endian byte_order_from, gdb_byte *to, int len_to,
371
                 enum bfd_endian byte_order_to)
372
{
373
  decNumber number;
374
  gdb_byte dec[16];
375
 
376
  match_endianness (from, len_from, byte_order_from, dec);
377
 
378
  decimal_to_number (dec, len_from, &number);
379
  decimal_from_number (&number, dec, len_to);
380
 
381
  match_endianness (dec, len_to, byte_order_to, to);
382
}

powered by: WebSVN 2.1.0

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