GDB (API)
/home/stan/gdb/src/gdb/dfp.c
Go to the documentation of this file.
00001 /* Decimal floating point support for GDB.
00002 
00003    Copyright (C) 2007-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "expression.h"
00022 #include "gdbtypes.h"
00023 #include "value.h"
00024 #include "dfp.h"
00025 
00026 /* The order of the following headers is important for making sure
00027    decNumber structure is large enough to hold decimal128 digits.  */
00028 
00029 #include "dpd/decimal128.h"
00030 #include "dpd/decimal64.h"
00031 #include "dpd/decimal32.h"
00032 
00033 /* In GDB, we are using an array of gdb_byte to represent decimal values.
00034    They are stored in host byte order.  This routine does the conversion if
00035    the target byte order is different.  */
00036 static void
00037 match_endianness (const gdb_byte *from, int len, enum bfd_endian byte_order,
00038                   gdb_byte *to)
00039 {
00040   int i;
00041 
00042 #if WORDS_BIGENDIAN
00043 #define OPPOSITE_BYTE_ORDER BFD_ENDIAN_LITTLE
00044 #else
00045 #define OPPOSITE_BYTE_ORDER BFD_ENDIAN_BIG
00046 #endif
00047 
00048   if (byte_order == OPPOSITE_BYTE_ORDER)
00049     for (i = 0; i < len; i++)
00050       to[i] = from[len - i - 1];
00051   else
00052     for (i = 0; i < len; i++)
00053       to[i] = from[i];
00054 
00055   return;
00056 }
00057 
00058 /* Helper function to get the appropriate libdecnumber context for each size
00059    of decimal float.  */
00060 static void
00061 set_decnumber_context (decContext *ctx, int len)
00062 {
00063   switch (len)
00064     {
00065       case 4:
00066         decContextDefault (ctx, DEC_INIT_DECIMAL32);
00067         break;
00068       case 8:
00069         decContextDefault (ctx, DEC_INIT_DECIMAL64);
00070         break;
00071       case 16:
00072         decContextDefault (ctx, DEC_INIT_DECIMAL128);
00073         break;
00074     }
00075 
00076   ctx->traps = 0;
00077 }
00078 
00079 /* Check for errors signaled in the decimal context structure.  */
00080 static void
00081 decimal_check_errors (decContext *ctx)
00082 {
00083   /* An error here could be a division by zero, an overflow, an underflow or
00084      an invalid operation (from the DEC_Errors constant in decContext.h).
00085      Since GDB doesn't complain about division by zero, overflow or underflow
00086      errors for binary floating, we won't complain about them for decimal
00087      floating either.  */
00088   if (ctx->status & DEC_IEEE_854_Invalid_operation)
00089     {
00090       /* Leave only the error bits in the status flags.  */
00091       ctx->status &= DEC_IEEE_854_Invalid_operation;
00092       error (_("Cannot perform operation: %s"),
00093              decContextStatusToString (ctx));
00094     }
00095 }
00096 
00097 /* Helper function to convert from libdecnumber's appropriate representation
00098    for computation to each size of decimal float.  */
00099 static void
00100 decimal_from_number (const decNumber *from, gdb_byte *to, int len)
00101 {
00102   decContext set;
00103 
00104   set_decnumber_context (&set, len);
00105 
00106   switch (len)
00107     {
00108       case 4:
00109         decimal32FromNumber ((decimal32 *) to, from, &set);
00110         break;
00111       case 8:
00112         decimal64FromNumber ((decimal64 *) to, from, &set);
00113         break;
00114       case 16:
00115         decimal128FromNumber ((decimal128 *) to, from, &set);
00116         break;
00117     }
00118 }
00119 
00120 /* Helper function to convert each size of decimal float to libdecnumber's
00121    appropriate representation for computation.  */
00122 static void
00123 decimal_to_number (const gdb_byte *from, int len, decNumber *to)
00124 {
00125   switch (len)
00126     {
00127       case 4:
00128         decimal32ToNumber ((decimal32 *) from, to);
00129         break;
00130       case 8:
00131         decimal64ToNumber ((decimal64 *) from, to);
00132         break;
00133       case 16:
00134         decimal128ToNumber ((decimal128 *) from, to);
00135         break;
00136       default:
00137         error (_("Unknown decimal floating point type."));
00138         break;
00139     }
00140 }
00141 
00142 /* Convert decimal type to its string representation.  LEN is the length
00143    of the decimal type, 4 bytes for decimal32, 8 bytes for decimal64 and
00144    16 bytes for decimal128.  */
00145 void
00146 decimal_to_string (const gdb_byte *decbytes, int len,
00147                    enum bfd_endian byte_order, char *s)
00148 {
00149   gdb_byte dec[16];
00150 
00151   match_endianness (decbytes, len, byte_order, dec);
00152 
00153   switch (len)
00154     {
00155       case 4:
00156         decimal32ToString ((decimal32 *) dec, s);
00157         break;
00158       case 8:
00159         decimal64ToString ((decimal64 *) dec, s);
00160         break;
00161       case 16:
00162         decimal128ToString ((decimal128 *) dec, s);
00163         break;
00164       default:
00165         error (_("Unknown decimal floating point type."));
00166         break;
00167     }
00168 }
00169 
00170 /* Convert the string form of a decimal value to its decimal representation.
00171    LEN is the length of the decimal type, 4 bytes for decimal32, 8 bytes for
00172    decimal64 and 16 bytes for decimal128.  */
00173 int
00174 decimal_from_string (gdb_byte *decbytes, int len, enum bfd_endian byte_order,
00175                      const char *string)
00176 {
00177   decContext set;
00178   gdb_byte dec[16];
00179 
00180   set_decnumber_context (&set, len);
00181 
00182   switch (len)
00183     {
00184       case 4:
00185         decimal32FromString ((decimal32 *) dec, string, &set);
00186         break;
00187       case 8:
00188         decimal64FromString ((decimal64 *) dec, string, &set);
00189         break;
00190       case 16:
00191         decimal128FromString ((decimal128 *) dec, string, &set);
00192         break;
00193       default:
00194         error (_("Unknown decimal floating point type."));
00195         break;
00196     }
00197 
00198   match_endianness (dec, len, byte_order, decbytes);
00199 
00200   /* Check for errors in the DFP operation.  */
00201   decimal_check_errors (&set);
00202 
00203   return 1;
00204 }
00205 
00206 /* Converts a value of an integral type to a decimal float of
00207    specified LEN bytes.  */
00208 void
00209 decimal_from_integral (struct value *from,
00210                        gdb_byte *to, int len, enum bfd_endian byte_order)
00211 {
00212   LONGEST l;
00213   gdb_byte dec[16];
00214   decNumber number;
00215   struct type *type;
00216 
00217   type = check_typedef (value_type (from));
00218 
00219   if (TYPE_LENGTH (type) > 4)
00220     /* libdecnumber can convert only 32-bit integers.  */
00221     error (_("Conversion of large integer to a "
00222              "decimal floating type is not supported."));
00223 
00224   l = value_as_long (from);
00225 
00226   if (TYPE_UNSIGNED (type))
00227     decNumberFromUInt32 (&number, (unsigned int) l);
00228   else
00229     decNumberFromInt32 (&number, (int) l);
00230 
00231   decimal_from_number (&number, dec, len);
00232   match_endianness (dec, len, byte_order, to);
00233 }
00234 
00235 /* Converts a value of a float type to a decimal float of
00236    specified LEN bytes.
00237 
00238    This is an ugly way to do the conversion, but libdecnumber does
00239    not offer a direct way to do it.  */
00240 void
00241 decimal_from_floating (struct value *from,
00242                        gdb_byte *to, int len, enum bfd_endian byte_order)
00243 {
00244   char *buffer;
00245 
00246   buffer = xstrprintf ("%.30" DOUBLEST_PRINT_FORMAT, value_as_double (from));
00247 
00248   decimal_from_string (to, len, byte_order, buffer);
00249 
00250   xfree (buffer);
00251 }
00252 
00253 /* Converts a decimal float of LEN bytes to a double value.  */
00254 DOUBLEST
00255 decimal_to_doublest (const gdb_byte *from, int len, enum bfd_endian byte_order)
00256 {
00257   char buffer[MAX_DECIMAL_STRING];
00258 
00259   /* This is an ugly way to do the conversion, but libdecnumber does
00260      not offer a direct way to do it.  */
00261   decimal_to_string (from, len, byte_order, buffer);
00262   return strtod (buffer, NULL);
00263 }
00264 
00265 /* Perform operation OP with operands X and Y with sizes LEN_X and LEN_Y
00266    and byte orders BYTE_ORDER_X and BYTE_ORDER_Y, and store value in
00267    RESULT with size LEN_RESULT and byte order BYTE_ORDER_RESULT.  */
00268 void
00269 decimal_binop (enum exp_opcode op,
00270                const gdb_byte *x, int len_x, enum bfd_endian byte_order_x,
00271                const gdb_byte *y, int len_y, enum bfd_endian byte_order_y,
00272                gdb_byte *result, int len_result,
00273                enum bfd_endian byte_order_result)
00274 {
00275   decContext set;
00276   decNumber number1, number2, number3;
00277   gdb_byte dec1[16], dec2[16], dec3[16];
00278 
00279   match_endianness (x, len_x, byte_order_x, dec1);
00280   match_endianness (y, len_y, byte_order_y, dec2);
00281 
00282   decimal_to_number (dec1, len_x, &number1);
00283   decimal_to_number (dec2, len_y, &number2);
00284 
00285   set_decnumber_context (&set, len_result);
00286 
00287   switch (op)
00288     {
00289       case BINOP_ADD:
00290         decNumberAdd (&number3, &number1, &number2, &set);
00291         break;
00292       case BINOP_SUB:
00293         decNumberSubtract (&number3, &number1, &number2, &set);
00294         break;
00295       case BINOP_MUL:
00296         decNumberMultiply (&number3, &number1, &number2, &set);
00297         break;
00298       case BINOP_DIV:
00299         decNumberDivide (&number3, &number1, &number2, &set);
00300         break;
00301       case BINOP_EXP:
00302         decNumberPower (&number3, &number1, &number2, &set);
00303         break;
00304       default:
00305         internal_error (__FILE__, __LINE__,
00306                         _("Unknown decimal floating point operation."));
00307         break;
00308     }
00309 
00310   /* Check for errors in the DFP operation.  */
00311   decimal_check_errors (&set);
00312 
00313   decimal_from_number (&number3, dec3, len_result);
00314 
00315   match_endianness (dec3, len_result, byte_order_result, result);
00316 }
00317 
00318 /* Returns true if X (which is LEN bytes wide) is the number zero.  */
00319 int
00320 decimal_is_zero (const gdb_byte *x, int len, enum bfd_endian byte_order)
00321 {
00322   decNumber number;
00323   gdb_byte dec[16];
00324 
00325   match_endianness (x, len, byte_order, dec);
00326   decimal_to_number (dec, len, &number);
00327 
00328   return decNumberIsZero (&number);
00329 }
00330 
00331 /* Compares two numbers numerically.  If X is less than Y then the return value
00332    will be -1.  If they are equal, then the return value will be 0.  If X is
00333    greater than the Y then the return value will be 1.  */
00334 int
00335 decimal_compare (const gdb_byte *x, int len_x, enum bfd_endian byte_order_x,
00336                  const gdb_byte *y, int len_y, enum bfd_endian byte_order_y)
00337 {
00338   decNumber number1, number2, result;
00339   decContext set;
00340   gdb_byte dec1[16], dec2[16];
00341   int len_result;
00342 
00343   match_endianness (x, len_x, byte_order_x, dec1);
00344   match_endianness (y, len_y, byte_order_y, dec2);
00345 
00346   decimal_to_number (dec1, len_x, &number1);
00347   decimal_to_number (dec2, len_y, &number2);
00348 
00349   /* Perform the comparison in the larger of the two sizes.  */
00350   len_result = len_x > len_y ? len_x : len_y;
00351   set_decnumber_context (&set, len_result);
00352 
00353   decNumberCompare (&result, &number1, &number2, &set);
00354 
00355   /* Check for errors in the DFP operation.  */
00356   decimal_check_errors (&set);
00357 
00358   if (decNumberIsNaN (&result))
00359     error (_("Comparison with an invalid number (NaN)."));
00360   else if (decNumberIsZero (&result))
00361     return 0;
00362   else if (decNumberIsNegative (&result))
00363     return -1;
00364   else
00365     return 1;
00366 }
00367 
00368 /* Convert a decimal value from a decimal type with LEN_FROM bytes to a
00369    decimal type with LEN_TO bytes.  */
00370 void
00371 decimal_convert (const gdb_byte *from, int len_from,
00372                  enum bfd_endian byte_order_from, gdb_byte *to, int len_to,
00373                  enum bfd_endian byte_order_to)
00374 {
00375   decNumber number;
00376   gdb_byte dec[16];
00377 
00378   match_endianness (from, len_from, byte_order_from, dec);
00379 
00380   decimal_to_number (dec, len_from, &number);
00381   decimal_from_number (&number, dec, len_to);
00382 
00383   match_endianness (dec, len_to, byte_order_to, to);
00384 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines