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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [gdb/] [dfp.c] - Blame information for rev 855

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

Line No. Rev Author Line
1 24 jeremybenn
/* Decimal floating point support for GDB.
2
 
3
   Copyright 2007, 2008 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, gdb_byte *to)
38
{
39
  int i;
40
 
41
#if WORDS_BIGENDIAN
42
#define OPPOSITE_BYTE_ORDER BFD_ENDIAN_LITTLE
43
#else
44
#define OPPOSITE_BYTE_ORDER BFD_ENDIAN_BIG
45
#endif
46
 
47
  if (gdbarch_byte_order (current_gdbarch) == OPPOSITE_BYTE_ORDER)
48
    for (i = 0; i < len; i++)
49
      to[i] = from[len - i - 1];
50
  else
51
    for (i = 0; i < len; i++)
52
      to[i] = from[i];
53
 
54
  return;
55
}
56
 
57
/* Helper function to get the appropriate libdecnumber context for each size
58
   of decimal float.  */
59
static void
60
set_decnumber_context (decContext *ctx, int len)
61
{
62
  switch (len)
63
    {
64
      case 4:
65
        decContextDefault (ctx, DEC_INIT_DECIMAL32);
66
        break;
67
      case 8:
68
        decContextDefault (ctx, DEC_INIT_DECIMAL64);
69
        break;
70
      case 16:
71
        decContextDefault (ctx, DEC_INIT_DECIMAL128);
72
        break;
73
    }
74
 
75
  ctx->traps = 0;
76
}
77
 
78
/* Check for errors signaled in the decimal context structure.  */
79
static void
80
decimal_check_errors (decContext *ctx)
81
{
82
  /* An error here could be a division by zero, an overflow, an underflow or
83
     an invalid operation (from the DEC_Errors constant in decContext.h).
84
     Since GDB doesn't complain about division by zero, overflow or underflow
85
     errors for binary floating, we won't complain about them for decimal
86
     floating either.  */
87
  if (ctx->status & DEC_IEEE_854_Invalid_operation)
88
    {
89
      /* Leave only the error bits in the status flags.  */
90
      ctx->status &= DEC_IEEE_854_Invalid_operation;
91
      error (_("Cannot perform operation: %s"), decContextStatusToString (ctx));
92
    }
93
}
94
 
95
/* Helper function to convert from libdecnumber's appropriate representation
96
   for computation to each size of decimal float.  */
97
static void
98
decimal_from_number (const decNumber *from, gdb_byte *to, int len)
99
{
100
  decContext set;
101
 
102
  set_decnumber_context (&set, len);
103
 
104
  switch (len)
105
    {
106
      case 4:
107
        decimal32FromNumber ((decimal32 *) to, from, &set);
108
        break;
109
      case 8:
110
        decimal64FromNumber ((decimal64 *) to, from, &set);
111
        break;
112
      case 16:
113
        decimal128FromNumber ((decimal128 *) to, from, &set);
114
        break;
115
    }
116
}
117
 
118
/* Helper function to convert each size of decimal float to libdecnumber's
119
   appropriate representation for computation.  */
120
static void
121
decimal_to_number (const gdb_byte *from, int len, decNumber *to)
122
{
123
  switch (len)
124
    {
125
      case 4:
126
        decimal32ToNumber ((decimal32 *) from, to);
127
        break;
128
      case 8:
129
        decimal64ToNumber ((decimal64 *) from, to);
130
        break;
131
      case 16:
132
        decimal128ToNumber ((decimal128 *) from, to);
133
        break;
134
      default:
135
        error (_("Unknown decimal floating point type.\n"));
136
        break;
137
    }
138
}
139
 
140
/* Convert decimal type to its string representation.  LEN is the length
141
   of the decimal type, 4 bytes for decimal32, 8 bytes for decimal64 and
142
   16 bytes for decimal128.  */
143
void
144
decimal_to_string (const gdb_byte *decbytes, int len, char *s)
145
{
146
  gdb_byte dec[16];
147
 
148
  match_endianness (decbytes, len, dec);
149
 
150
  switch (len)
151
    {
152
      case 4:
153
        decimal32ToString ((decimal32 *) dec, s);
154
        break;
155
      case 8:
156
        decimal64ToString ((decimal64 *) dec, s);
157
        break;
158
      case 16:
159
        decimal128ToString ((decimal128 *) dec, s);
160
        break;
161
      default:
162
        error (_("Unknown decimal floating point type."));
163
        break;
164
    }
165
}
166
 
167
/* Convert the string form of a decimal value to its decimal representation.
168
   LEN is the length of the decimal type, 4 bytes for decimal32, 8 bytes for
169
   decimal64 and 16 bytes for decimal128.  */
170
int
171
decimal_from_string (gdb_byte *decbytes, int len, const char *string)
172
{
173
  decContext set;
174
  gdb_byte dec[16];
175
 
176
  set_decnumber_context (&set, len);
177
 
178
  switch (len)
179
    {
180
      case 4:
181
        decimal32FromString ((decimal32 *) dec, string, &set);
182
        break;
183
      case 8:
184
        decimal64FromString ((decimal64 *) dec, string, &set);
185
        break;
186
      case 16:
187
        decimal128FromString ((decimal128 *) dec, string, &set);
188
        break;
189
      default:
190
        error (_("Unknown decimal floating point type."));
191
        break;
192
    }
193
 
194
  match_endianness (dec, len, decbytes);
195
 
196
  /* Check for errors in the DFP operation.  */
197
  decimal_check_errors (&set);
198
 
199
  return 1;
200
}
201
 
202
/* Converts a value of an integral type to a decimal float of
203
   specified LEN bytes.  */
204
void
205
decimal_from_integral (struct value *from, gdb_byte *to, int len)
206
{
207
  LONGEST l;
208
  gdb_byte dec[16];
209
  decNumber number;
210
  struct type *type;
211
 
212
  type = check_typedef (value_type (from));
213
 
214
  if (TYPE_LENGTH (type) > 4)
215
    /* libdecnumber can convert only 32-bit integers.  */
216
    error (_("Conversion of large integer to a decimal floating type is not supported."));
217
 
218
  l = value_as_long (from);
219
 
220
  if (TYPE_UNSIGNED (type))
221
    decNumberFromUInt32 (&number, (unsigned int) l);
222
  else
223
    decNumberFromInt32 (&number, (int) l);
224
 
225
  decimal_from_number (&number, dec, len);
226
  match_endianness (dec, len, to);
227
}
228
 
229
/* Converts a value of a float type to a decimal float of
230
   specified LEN bytes.
231
 
232
   This is an ugly way to do the conversion, but libdecnumber does
233
   not offer a direct way to do it.  */
234
void
235
decimal_from_floating (struct value *from, gdb_byte *to, int len)
236
{
237
  char *buffer;
238
  int ret;
239
 
240
  ret = asprintf (&buffer, "%.30" DOUBLEST_PRINT_FORMAT,
241
                  value_as_double (from));
242
  if (ret < 0)
243
    error (_("Error in memory allocation for conversion to decimal float."));
244
 
245
  decimal_from_string (to, len, buffer);
246
 
247
  free (buffer);
248
}
249
 
250
/* Converts a decimal float of LEN bytes to a double value.  */
251
DOUBLEST
252
decimal_to_doublest (const gdb_byte *from, int len)
253
{
254
  char buffer[MAX_DECIMAL_STRING];
255
 
256
  /* This is an ugly way to do the conversion, but libdecnumber does
257
     not offer a direct way to do it.  */
258
  decimal_to_string (from, len, buffer);
259
  return strtod (buffer, NULL);
260
}
261
 
262
/* Check if operands have the same size and convert them to the
263
   biggest of the two if necessary.  */
264
static int
265
promote_decimal (gdb_byte *x, int len_x, gdb_byte *y, int len_y)
266
{
267
  int len_result;
268
  decNumber number;
269
 
270
  if (len_x < len_y)
271
    {
272
      decimal_to_number (x, len_x, &number);
273
      decimal_from_number (&number, x, len_y);
274
      len_result = len_y;
275
    }
276
  else if (len_x > len_y)
277
    {
278
      decimal_to_number (y, len_y, &number);
279
      decimal_from_number (&number, y, len_x);
280
      len_result = len_x;
281
    }
282
  else
283
    len_result = len_x;
284
 
285
  return len_result;
286
}
287
 
288
/* Perform operation OP with operands X and Y and store value in RESULT.
289
   If LEN_X and LEN_Y are not equal, RESULT will have the size of the biggest
290
   of the two, and LEN_RESULT will be set accordingly.  */
291
void
292
decimal_binop (enum exp_opcode op, const gdb_byte *x, int len_x,
293
               const gdb_byte *y, int len_y, gdb_byte *result, int *len_result)
294
{
295
  decContext set;
296
  decNumber number1, number2, number3;
297
  gdb_byte dec1[16], dec2[16], dec3[16];
298
 
299
  match_endianness (x, len_x, dec1);
300
  match_endianness (y, len_y, dec2);
301
 
302
  *len_result = promote_decimal (dec1, len_x, dec2, len_y);
303
 
304
  /* Both operands are of size *len_result from now on.  */
305
 
306
  decimal_to_number (dec1, *len_result, &number1);
307
  decimal_to_number (dec2, *len_result, &number2);
308
 
309
  set_decnumber_context (&set, *len_result);
310
 
311
  switch (op)
312
    {
313
      case BINOP_ADD:
314
        decNumberAdd (&number3, &number1, &number2, &set);
315
        break;
316
      case BINOP_SUB:
317
        decNumberSubtract (&number3, &number1, &number2, &set);
318
        break;
319
      case BINOP_MUL:
320
        decNumberMultiply (&number3, &number1, &number2, &set);
321
        break;
322
      case BINOP_DIV:
323
        decNumberDivide (&number3, &number1, &number2, &set);
324
        break;
325
      case BINOP_EXP:
326
        decNumberPower (&number3, &number1, &number2, &set);
327
        break;
328
      default:
329
        internal_error (__FILE__, __LINE__,
330
                        _("Unknown decimal floating point operation."));
331
        break;
332
    }
333
 
334
  /* Check for errors in the DFP operation.  */
335
  decimal_check_errors (&set);
336
 
337
  decimal_from_number (&number3, dec3, *len_result);
338
 
339
  match_endianness (dec3, *len_result, result);
340
}
341
 
342
/* Returns true if X (which is LEN bytes wide) is the number zero.  */
343
int
344
decimal_is_zero (const gdb_byte *x, int len)
345
{
346
  decNumber number;
347
  gdb_byte dec[16];
348
 
349
  match_endianness (x, len, dec);
350
  decimal_to_number (dec, len, &number);
351
 
352
  return decNumberIsZero (&number);
353
}
354
 
355
/* Compares two numbers numerically.  If X is less than Y then the return value
356
   will be -1.  If they are equal, then the return value will be 0.  If X is
357
   greater than the Y then the return value will be 1.  */
358
int
359
decimal_compare (const gdb_byte *x, int len_x, const gdb_byte *y, int len_y)
360
{
361
  decNumber number1, number2, result;
362
  decContext set;
363
  gdb_byte dec1[16], dec2[16];
364
  int len_result;
365
 
366
  match_endianness (x, len_x, dec1);
367
  match_endianness (y, len_y, dec2);
368
 
369
  len_result = promote_decimal (dec1, len_x, dec2, len_y);
370
 
371
  decimal_to_number (dec1, len_result, &number1);
372
  decimal_to_number (dec2, len_result, &number2);
373
 
374
  set_decnumber_context (&set, len_result);
375
 
376
  decNumberCompare (&result, &number1, &number2, &set);
377
 
378
  /* Check for errors in the DFP operation.  */
379
  decimal_check_errors (&set);
380
 
381
  if (decNumberIsNaN (&result))
382
    error (_("Comparison with an invalid number (NaN)."));
383
  else if (decNumberIsZero (&result))
384
    return 0;
385
  else if (decNumberIsNegative (&result))
386
    return -1;
387
  else
388
    return 1;
389
}
390
 
391
/* Convert a decimal value from a decimal type with LEN_FROM bytes to a
392
   decimal type with LEN_TO bytes.  */
393
void
394
decimal_convert (const gdb_byte *from, int len_from, gdb_byte *to,
395
                 int len_to)
396
{
397
  decNumber number;
398
 
399
  decimal_to_number (from, len_from, &number);
400
  decimal_from_number (&number, to, len_to);
401
}

powered by: WebSVN 2.1.0

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