GDB (API)
|
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 }