Re: [RFC] decimal float point patch based on libdecnumber: gdb patch

Wu Zhou
2006-08-01T10:51:40Z

Sorry, forget to add changelog entries. And also merge with the
latest cvs source. Here is the modified patch. Please review and
comment.

2006-08-01 Wu Zhou <woodzltc@cn.ibm.com>

* expression.h (enum exp_opcode): Add an opcode (OP_DECFLOAT) for
DFP constants.
(union exp_element): Add decfloatconst to represent DFP elements,
which is 16 bytes by default.
* parser-defs.h (write_exp_elt_decfloatcst): Prototype.
* parse.c (write_exp_elt_decfloatcst): New function to write a decimal
float const into the expression.
(operator_length_standard): Set operator length for OP_DECFLOAT
to 4.
* c-exp.y (YYSTYPE): Add typed_val_decfloat for decimal floating
point in YYSTYPE union.
Add token DECFLOAT for typed_val_decfloat.
Add expression element handling code for DECFLOAT.
(parse_number): Parse DFP constants, which end with suffix 'df',
'dd' or 'dl'. Return DECFLOAT.
* c-lang.c (c_create_fundamental_type): Create fundamental types
for DFP.
* c-valprint.c (c_val_print): Call print_decimal_floating to print
DFP values.
* dwarf2read.c (read_base_type): Read DW_ATE_decimal_float attribute
code and return TYPE_CODE_DECFLOAT.
(dwarf_base_type): Set dwarf2_fundamental_type for DFP values.
* eval.c (evaluate_subexp_standard): Call value_from_decfloat to
handle OP_DECFLOAT.
* gdbtypes.h: Add three fundamental types for DFP.
(enum type_code): Add TYPE_CODE_DECFLOAT as a type code for DFP.
(struct builtin_type): Add builtin_decfloat, builtin_decdouble
and builtin_declong.
* gdbtypes.c: Add three builtin types for DFP.
(build_gdbtypes): Build these three builtin types for DFP.
(gdbtypes_post_init): Initialize builtin_decfloat, builtin_decdouble
and builtin_declong.
* value.h (value_from_decfloat): Prototype.
(print_decimal_floating): Prototype.
* valprint.c (print_decimal_floating): New function to print DFP
values.
* value.c (value_from_decfloat): New function to get the value
from a decimal floating point.
* valarith.c (value_neg): Add some code to handle the negation
operation of DFP values.
* dfp.h: New header file for decimal floating point support in
GDB.
* dfp.c: New source file for decimal floating point support in
GDB. Implement decimal_from_string and decimal_to_string based
on libdecnumber API.
* Makefile.in (LIBDECNUMBER_DIR, LIBDECNUMBER, LIBDECNUMBER_SRC
LIBDECNUMBER_CFLAGS): New macros for libdecnumber.
(INTERNAL_CFLAGS_BASE): Add LIBDECNUMBER_CFLAGS in.
(INSTALLED_LIBS): Add -ldecnumber in.
(CLIBS): Add LIBDECNUMBER in.
(decimal128_h, decimal64_h, decimal32_h): New macros for decimal headers.
(dfp_h): New macros for decimal floating point.
(dfp.o): New target.
(COMMON_OBS): Add dfp.o in.
(valprint.o): Add dfp_h as a new dependence.

Index: expression.h
===================================================================
RCS file: /cvs/src/src/gdb/expression.h,v
retrieving revision 1.18
diff -c -3 -p -r1.18 expression.h
*** expression.h 17 Dec 2005 22:33:59 -0000 1.18
--- expression.h 1 Aug 2006 10:30:16 -0000
***************
*** 1,7 ****
/* Definitions for expressions stored in reversed prefix form, for GDB.

! Copyright (C) 1986, 1989, 1992, 1994, 2000, 2003, 2005 Free Software
! Foundation, Inc.

This file is part of GDB.

--- 1,7 ----
/* Definitions for expressions stored in reversed prefix form, for GDB.

! Copyright (C) 1986, 1989, 1992, 1994, 2000, 2003, 2005, 2006
! Free Software Foundation, Inc.

This file is part of GDB.

*************** enum exp_opcode
*** 327,332 ****
--- 327,337 ----
/* A F90 array range operator (for "exp:exp", "exp:", ":exp"
and ":"). */
OP_F90_RANGE,

+ /* OP_DECFLOAT is followed by a type pointer in the next exp_element
+ and a dec long constant value in the following exp_element.
+ Then comes another OP_DECFLOAT. */
+ OP_DECFLOAT,
+
/* First extension operator. Individual language modules define
extra operators they need as constants with values
OP_LANGUAGE_SPECIFIC0 + k, for k >= 0, using a separate
*************** union exp_element
*** 354,359 ****
--- 359,365 ----
struct symbol *symbol;
LONGEST longconst;
DOUBLEST doubleconst;
+ gdb_byte decfloatconst[16];
/* Really sizeof (union exp_element) characters (or less for the last
element of a string). */
char string;
Index: parser-defs.h
===================================================================
RCS file: /cvs/src/src/gdb/parser-defs.h,v
retrieving revision 1.20
diff -c -3 -p -r1.20 parser-defs.h
*** parser-defs.h 17 Dec 2005 22:34:01 -0000 1.20
--- parser-defs.h 1 Aug 2006 10:30:16 -0000
***************
*** 1,7 ****
/* Parser definitions for GDB.

Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
! 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc.

Modified from expread.y by the Department of Computer Science at the
State University of New York at Buffalo.
--- 1,7 ----
/* Parser definitions for GDB.

Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
! 1997, 1998, 1999, 2000, 2002, 2006 Free Software Foundation, Inc.

Modified from expread.y by the Department of Computer Science at the
State University of New York at Buffalo.
*************** extern void write_exp_elt_longcst (LONGE
*** 121,126 ****
--- 121,128 ----

extern void write_exp_elt_dblcst (DOUBLEST);

+ extern void write_exp_elt_decfloatcst (gdb_byte *);
+
extern void write_exp_elt_type (struct type *);

extern void write_exp_elt_intern (struct internalvar *);
Index: parse.c
===================================================================
RCS file: /cvs/src/src/gdb/parse.c,v
retrieving revision 1.53
diff -c -3 -p -r1.53 parse.c
*** parse.c 6 Jul 2006 14:00:48 -0000 1.53
--- parse.c 1 Aug 2006 10:30:17 -0000
***************
*** 1,7 ****
/* Parse expressions for GDB.

Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
! 1997, 1998, 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.

Modified from expread.y by the Department of Computer Science at the
State University of New York at Buffalo, 1991.
--- 1,8 ----
/* Parse expressions for GDB.

Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
! 1997, 1998, 1999, 2000, 2001, 2004, 2005, 2006
! Free Software Foundation, Inc.

Modified from expread.y by the Department of Computer Science at the
State University of New York at Buffalo, 1991.
*************** write_exp_elt_dblcst (DOUBLEST expelt)
*** 241,246 ****
--- 242,259 ----
}

void
+ write_exp_elt_decfloatcst (gdb_byte expelt[16])
+ {
+ union exp_element tmp;
+ int index;
+
+ for (index = 0; index < 16; index++)
+ tmp.decfloatconst[index] = expelt[index];
+
+ write_exp_elt (tmp);
+ }
+
+ void
write_exp_elt_type (struct type *expelt)
{
union exp_element tmp;
*************** operator_length_standard (struct express
*** 864,869 ****
--- 877,883 ----

case OP_LONG:
case OP_DOUBLE:
+ case OP_DECFLOAT:
case OP_VAR_VALUE:
oplen = 4;
break;
Index: c-exp.y
===================================================================
RCS file: /cvs/src/src/gdb/c-exp.y,v
retrieving revision 1.34
diff -c -3 -p -r1.34 c-exp.y
*** c-exp.y 23 Feb 2006 18:43:41 -0000 1.34
--- c-exp.y 1 Aug 2006 10:30:17 -0000
*************** Boston, MA 02110-1301, USA. */
*** 53,58 ****
--- 53,59 ----
#include "charset.h"
#include "block.h"
#include "cp-support.h"
+ #include "dfp.h"

/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitiously global symbol names, so we can have multiple
*************** void yyerror (char *);
*** 131,136 ****
--- 132,141 ----
DOUBLEST dval;
struct type *type;
} typed_val_float;
+ struct {
+ gdb_byte val[16];
+ struct type *type;
+ } typed_val_decfloat;
struct symbol *sym;
struct type *tval;
struct stoken sval;
*************** static int parse_number (char *, int, in
*** 163,168 ****
--- 168,174 ----

%token <typed_val_int> INT
%token <typed_val_float> FLOAT
+ %token <typed_val_decfloat> DECFLOAT

/* Both NAME and TYPENAME tokens represent symbols in the input,
and both convey their data as strings.
*************** exp : FLOAT
*** 497,502 ****
--- 503,515 ----
write_exp_elt_opcode (OP_DOUBLE); }
;

+ exp : DECFLOAT
+ { write_exp_elt_opcode (OP_DECFLOAT);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_decfloatcst ($1.val);
+ write_exp_elt_opcode (OP_DECFLOAT); }
+ ;
+
exp : variable
;

*************** parse_number (p, len, parsed_float, puti
*** 1080,1085 ****
--- 1093,1132 ----
char saved_char = p[len];

p[len] = 0; /* null-terminate the token */
+
+ /* If it ends at "df", "dd" or "dl", take it as type of
decimal floating
+ point. Return DECFLOAT. */
+
+ if (p[len - 2] == 'd' && p[len - 1] == 'f')
+ {
+ p[len - 2] = '\0';
+ putithere->typed_val_decfloat.type =
+ builtin_type (current_gdbarch)->builtin_decfloat;
+ decimal_from_string (putithere->typed_val_decfloat.val, 4, p);
+ p[len] = saved_char;
+ return (DECFLOAT);
+ }
+
+ if (p[len - 2] == 'd' && p[len - 1] == 'd')
+ {
+ p[len - 2] = '\0';
+ putithere->typed_val_decfloat.type =
+ builtin_type (current_gdbarch)->builtin_decdouble;
+ decimal_from_string (putithere->typed_val_decfloat.val, 8, p);
+ p[len] = saved_char;
+ return (DECFLOAT);
+ }
+
+ if (p[len - 2] == 'd' && p[len - 1] == 'l')
+ {
+ p[len - 2] = '\0';
+ putithere->typed_val_decfloat.type =
+ builtin_type (current_gdbarch)->builtin_declong;
+ decimal_from_string (putithere->typed_val_decfloat.val, 16, p);
+ p[len] = saved_char;
+ return (DECFLOAT);
+ }
+
num = sscanf (p, DOUBLEST_SCAN_FORMAT "%s",
&putithere->typed_val_float.dval, s);
p[len] = saved_char; /* restore the input stream */
Index: c-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/c-lang.c,v
retrieving revision 1.39
diff -c -3 -p -r1.39 c-lang.c
*** c-lang.c 17 Dec 2005 22:33:59 -0000 1.39
--- c-lang.c 1 Aug 2006 10:30:17 -0000
***************
*** 1,7 ****
/* C language support routines for GDB, the GNU debugger.

Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002,
! 2003, 2004, 2005 Free Software Foundation, Inc.

This file is part of GDB.

--- 1,7 ----
/* C language support routines for GDB, the GNU debugger.

Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002,
! 2003, 2004, 2005, 2006 Free Software Foundation, Inc.

This file is part of GDB.

*************** c_create_fundamental_type (struct objfil
*** 322,327 ****
--- 322,342 ----
TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
0, "long double", objfile);
break;
+ case FT_DECFLOAT:
+ type = init_type (TYPE_CODE_DECFLOAT,
+ 32 / 8,
+ 0, "decimal float", objfile);
+ break;
+ case FT_DBL_PREC_DECFLOAT:
+ type = init_type (TYPE_CODE_DECFLOAT,
+ 64 / 8,
+ 0, "decimal double", objfile);
+ break;
+ case FT_EXT_PREC_DECFLOAT:
+ type = init_type (TYPE_CODE_DECFLOAT,
+ 128 / 8,
+ 0, "decimal long double", objfile);
+ break;
case FT_COMPLEX:
type = init_type (TYPE_CODE_FLT,
2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
Index: c-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-valprint.c,v
retrieving revision 1.39
diff -c -3 -p -r1.39 c-valprint.c
*** c-valprint.c 18 Jan 2006 21:24:19 -0000 1.39
--- c-valprint.c 1 Aug 2006 10:30:17 -0000
*************** c_val_print (struct type *type, const gd
*** 433,445 ****

case TYPE_CODE_FLT:
if (format)
! {
! print_scalar_formatted (valaddr + embedded_offset, type, format,
0, stream);
! }
else
! {
! print_floating (valaddr + embedded_offset, type, stream);
! }
break;

case TYPE_CODE_METHOD:
--- 433,448 ----

case TYPE_CODE_FLT:
if (format)
! print_scalar_formatted (valaddr + embedded_offset, type, format, 0,
stream);
else
! print_floating (valaddr + embedded_offset, type, stream);
! break;
!
! case TYPE_CODE_DECFLOAT:
! if (format)
! print_scalar_formatted (valaddr + embedded_offset, type, format, 0,
stream);
! else
! print_decimal_floating (valaddr + embedded_offset, type, stream);
break;

case TYPE_CODE_METHOD:
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.201
diff -c -3 -p -r1.201 dwarf2read.c
*** dwarf2read.c 24 Jul 2006 21:37:04 -0000 1.201
--- dwarf2read.c 1 Aug 2006 10:30:17 -0000
*************** read_base_type (struct die_info *die, st
*** 4747,4752 ****
--- 4747,4755 ----
case DW_ATE_complex_float:
code = TYPE_CODE_COMPLEX;
break;
+ case DW_ATE_decimal_float:
+ code = TYPE_CODE_DECFLOAT;
+ break;
case DW_ATE_float:
code = TYPE_CODE_FLT;
break;
*************** dwarf_base_type (int encoding, int size,
*** 7517,7539 ****
return type;
case DW_ATE_complex_float:
if (size == 16)
! {
! type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_COMPLEX, cu);
! }
else
! {
! type = dwarf2_fundamental_type (objfile, FT_COMPLEX, cu);
! }
return type;
case DW_ATE_float:
if (size == 8)
! {
! type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT, cu);
! }
else
! {
! type = dwarf2_fundamental_type (objfile, FT_FLOAT, cu);
! }
return type;
case DW_ATE_signed:
switch (size)
--- 7520,7542 ----
return type;
case DW_ATE_complex_float:
if (size == 16)
! type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_COMPLEX, cu);
else
! type = dwarf2_fundamental_type (objfile, FT_COMPLEX, cu);
return type;
case DW_ATE_float:
if (size == 8)
! type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT, cu);
else
! type = dwarf2_fundamental_type (objfile, FT_FLOAT, cu);
! return type;
! case DW_ATE_decimal_float:
! if (size == 16)
! type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_DECFLOAT, cu);
! else if (size == 8)
! type = dwarf2_fundamental_type (objfile, FT_EXT_PREC_DECFLOAT, cu);
! else
! type = dwarf2_fundamental_type (objfile, FT_DECFLOAT, cu);
return type;
case DW_ATE_signed:
switch (size)
Index: eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.63
diff -c -3 -p -r1.63 eval.c
*** eval.c 25 Jul 2006 04:24:50 -0000 1.63
--- eval.c 1 Aug 2006 10:30:18 -0000
***************
*** 1,8 ****
/* Evaluate expressions for GDB.

Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
! 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 Free
! Software Foundation, Inc.

This file is part of GDB.

--- 1,8 ----
/* Evaluate expressions for GDB.

Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
! 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006
! Free Software Foundation, Inc.

This file is part of GDB.

*************** evaluate_subexp_standard (struct type *e
*** 451,456 ****
--- 451,461 ----
return value_from_double (exp->elts[pc + 1].type,
exp->elts[pc + 2].doubleconst);

+ case OP_DECFLOAT:
+ (*pos) += 3;
+ return value_from_decfloat (expect_type, exp->elts[pc + 1].type,
+ exp->elts[pc + 2].decfloatconst);
+
case OP_VAR_VALUE:
(*pos) += 3;
if (noside == EVAL_SKIP)
Index: gdbtypes.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.h,v
retrieving revision 1.65
diff -c -3 -p -r1.65 gdbtypes.h
*** gdbtypes.h 1 Feb 2006 23:14:10 -0000 1.65
--- gdbtypes.h 1 Aug 2006 10:30:18 -0000
*************** struct block;
*** 67,73 ****
#define FT_UNSIGNED_BYTE 27
#define FT_TEMPLATE_ARG 28

! #define FT_NUM_MEMBERS 29 /* Highest FT_* above, plus one. */

/* Some macros for char-based bitfields. */

--- 67,78 ----
#define FT_UNSIGNED_BYTE 27
#define FT_TEMPLATE_ARG 28

! /* The following three fundamental types are for decimal floating point. */
! #define FT_DECFLOAT 29
! #define FT_DBL_PREC_DECFLOAT 30
! #define FT_EXT_PREC_DECFLOAT 31
!
! #define FT_NUM_MEMBERS 32 /* Highest FT_* above, plus one. */

/* Some macros for char-based bitfields. */

*************** enum type_code
*** 159,165 ****
TYPE_CODE_TEMPLATE, /* C++ template */
TYPE_CODE_TEMPLATE_ARG, /* C++ template arg */

! TYPE_CODE_NAMESPACE /* C++ namespace. */
};

/* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an
--- 164,172 ----
TYPE_CODE_TEMPLATE, /* C++ template */
TYPE_CODE_TEMPLATE_ARG, /* C++ template arg */

! TYPE_CODE_NAMESPACE, /* C++ namespace. */
!
! TYPE_CODE_DECFLOAT /* Decimal floating point. */
};

/* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an
*************** struct builtin_type
*** 1005,1010 ****
--- 1012,1020 ----
struct type *builtin_bool;
struct type *builtin_long_long;
struct type *builtin_unsigned_long_long;
+ struct type *builtin_decfloat;
+ struct type *builtin_decdouble;
+ struct type *builtin_declong;
};

/* Return the type table for the specified architecture. */
*************** extern struct type *builtin_type_complex
*** 1028,1033 ****
--- 1038,1046 ----
extern struct type *builtin_type_double_complex;
extern struct type *builtin_type_string;
extern struct type *builtin_type_bool;
+ extern struct type *builtin_type_decfloat;
+ extern struct type *builtin_type_decdouble;
+ extern struct type *builtin_type_declong;

/* Address/pointer types: */
/* (C) Language `pointer to data' type. Some target platforms use an
Index: gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.105
diff -c -3 -p -r1.105 gdbtypes.c
*** gdbtypes.c 1 Mar 2006 19:34:46 -0000 1.105
--- gdbtypes.c 1 Aug 2006 10:30:18 -0000
*************** struct type *builtin_type_int128;
*** 76,81 ****
--- 76,87 ----
struct type *builtin_type_uint128;
struct type *builtin_type_bool;

+ /* The following three are about decimal floating point types, which are now
+ considered as potential extension to C99 standard. */
+ struct type *builtin_type_decfloat;
+ struct type *builtin_type_decdouble;
+ struct type *builtin_type_declong;
+
/* 128 bit long vector types */
struct type *builtin_type_v2_double;
struct type *builtin_type_v4_float;
*************** build_gdbtypes (void)
*** 3379,3384 ****
--- 3385,3405 ----
#if 0
TYPE_FLOATFORMAT (builtin_type_long_double) = TARGET_LONG_DOUBLE_FORMAT;
#endif
+
+ /* Builtin types for decimal floating point types. */
+ builtin_type_decfloat =
+ init_type (TYPE_CODE_DECFLOAT, 32 / 8,
+ 0,
+ "decimal float", (struct objfile *) NULL);
+ builtin_type_decdouble =
+ init_type (TYPE_CODE_DECFLOAT, 64 / 8,
+ 0,
+ "decimal double", (struct objfile *) NULL);
+ builtin_type_declong =
+ init_type (TYPE_CODE_DECFLOAT, 128 / 8,
+ 0,
+ "decimal long double", (struct objfile *) NULL);
+
builtin_type_complex =
init_type (TYPE_CODE_COMPLEX, 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
0,
*************** gdbtypes_post_init (struct gdbarch *gdba
*** 3604,3609 ****
--- 3625,3645 ----
0,
"bool", (struct objfile *) NULL);

+ /* The following three are about decimal floating point types, which are
+ 32-bits, 64-bits and 128-bits respectively. */
+ builtin_type->builtin_decfloat =
+ init_type (TYPE_CODE_DECFLOAT, 32 / 8,
+ 0,
+ "decimal float", (struct objfile *) NULL);
+ builtin_type->builtin_decdouble =
+ init_type (TYPE_CODE_DECFLOAT, 64 / 8,
+ 0,
+ "decimal double", (struct objfile *) NULL);
+ builtin_type->builtin_declong =
+ init_type (TYPE_CODE_DECFLOAT, 128 / 8,
+ 0,
+ "decimal long double", (struct objfile *) NULL);
+
/* Pointer/Address types. */

/* NOTE: on some targets, addresses and pointers are not necessarily
*************** _initialize_gdbtypes (void)
*** 3742,3747 ****
--- 3778,3786 ----
DEPRECATED_REGISTER_GDBARCH_SWAP (builtin_type_void_func_ptr);
DEPRECATED_REGISTER_GDBARCH_SWAP (builtin_type_CORE_ADDR);
DEPRECATED_REGISTER_GDBARCH_SWAP (builtin_type_bfd_vma);
+ DEPRECATED_REGISTER_GDBARCH_SWAP (builtin_type_decfloat);
+ DEPRECATED_REGISTER_GDBARCH_SWAP (builtin_type_decdouble);
+ DEPRECATED_REGISTER_GDBARCH_SWAP (builtin_type_declong);
deprecated_register_gdbarch_swap (NULL, 0, build_gdbtypes);

/* Note: These types do not need to be swapped - they are target
Index: value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.92
diff -c -3 -p -r1.92 value.h
*** value.h 13 Jul 2006 04:31:42 -0000 1.92
--- value.h 1 Aug 2006 10:30:18 -0000
***************
*** 1,7 ****
/* Definitions for values of C expressions, for GDB.

Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
! 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.

This file is part of GDB.
--- 1,7 ----
/* Definitions for values of C expressions, for GDB.

Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
! 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.

This file is part of GDB.
*************** extern LONGEST unpack_field_as_long (str
*** 274,279 ****
--- 274,282 ----
extern struct value *value_from_longest (struct type *type, LONGEST num);
extern struct value *value_from_pointer (struct type *type, CORE_ADDR addr);
extern struct value *value_from_double (struct type *type, DOUBLEST num);
+ extern struct value *value_from_decfloat (struct type *expect_type,
+ struct type *type,
+ gdb_byte decbytes[16]);
extern struct value *value_from_string (char *string);

extern struct value *value_at (struct type *type, CORE_ADDR addr);
*************** extern void print_longest (struct ui_fil
*** 473,478 ****
--- 476,484 ----
extern void print_floating (const gdb_byte *valaddr, struct type *type,
struct ui_file *stream);

+ extern void print_decimal_floating (const gdb_byte *valaddr, struct
type *type,
+ struct ui_file *stream);
+
extern int value_print (struct value *val, struct ui_file *stream,
int format,
enum val_prettyprint pretty);

Index: value.c
===================================================================
RCS file: /cvs/src/src/gdb/value.c,v
retrieving revision 1.36
diff -c -3 -p -r1.36 value.c
*** value.c 31 Mar 2006 10:36:18 -0000 1.36
--- value.c 1 Aug 2006 10:30:18 -0000
***************
*** 37,42 ****
--- 37,43 ----
#include "gdb_assert.h"
#include "regcache.h"
#include "block.h"
+ #include "dfp.h"

/* Prototypes for exported functions. */

*************** value_from_double (struct type *type, DO
*** 1610,1615 ****
--- 1611,1637 ----
}

struct value *
+ value_from_decfloat (struct type *expect_type, struct type *type,
+ gdb_byte decbytes[16])
+ {
+ struct value *val = allocate_value (type);
+ int len = TYPE_LENGTH (type);
+
+ if (expect_type)
+ {
+ int expect_len = TYPE_LENGTH (expect_type);
+ char decstr[128];
+ int real_len;
+
+ decimal_to_string (decbytes, len, decstr);
+ decimal_from_string (decbytes, expect_len, decstr);
+ }
+
+ memcpy (value_contents_raw (val), decbytes, len);
+ return val;
+ }
+
+ struct value *
coerce_ref (struct value *arg)
{
struct type *value_type_arg_tmp = check_typedef (value_type (arg));
Index: valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/valprint.c,v
retrieving revision 1.60
diff -c -3 -p -r1.60 valprint.c
*** valprint.c 15 May 2006 16:53:38 -0000 1.60
--- valprint.c 1 Aug 2006 10:30:18 -0000
***************
*** 35,40 ****
--- 35,41 ----
#include "floatformat.h"
#include "doublest.h"
#include "exceptions.h"
+ #include "dfp.h"

#include <errno.h>

*************** print_floating (const gdb_byte *valaddr,
*** 496,501 ****
--- 497,514 ----
}

void
+ print_decimal_floating (const gdb_byte *valaddr, struct type *type,
+ struct ui_file *stream)
+ {
+ char decstr[128];
+ unsigned len = TYPE_LENGTH (type);
+
+ decimal_to_string (valaddr, len, decstr);
+ fputs_filtered (decstr, stream);
+ return;
+ }
+
+ void
print_binary_chars (struct ui_file *stream, const gdb_byte *valaddr,
unsigned len)
{
Index: valarith.c
===================================================================
RCS file: /cvs/src/src/gdb/valarith.c,v
retrieving revision 1.45
diff -c -3 -p -r1.45 valarith.c
*** valarith.c 24 Jan 2006 21:21:12 -0000 1.45
--- valarith.c 1 Aug 2006 10:30:18 -0000
***************
*** 1,7 ****
/* Perform arithmetic and other operations on values, for GDB.

Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
! 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.

This file is part of GDB.
--- 1,7 ----
/* Perform arithmetic and other operations on values, for GDB.

Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
! 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.

This file is part of GDB.
*************** value_neg (struct value *arg1)
*** 1378,1383 ****
--- 1378,1397 ----

type = check_typedef (value_type (arg1));

+ if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+ {
+ struct value *val = allocate_value (result_type);
+ int len = TYPE_LENGTH (type);
+ gdb_byte *decbytes = (gdb_byte *) value_contents (arg1);
+
+ if (gdbarch_byte_order (current_gdbarch))
+ decbytes[len-1] = decbytes[len - 1] | 0x80;
+ else
+ decbytes[0] = decbytes[0] | 0x80;
+ memcpy (value_contents_raw (val), decbytes, 16);
+ return val;
+ }
+
if (TYPE_CODE (type) == TYPE_CODE_FLT)
return value_from_double (result_type, -value_as_double (arg1));
else if (is_integral_type (type))
Index: dfp.h
===================================================================
RCS file: dfp.h
diff -N dfp.h
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- dfp.h 1 Aug 2006 10:30:18 -0000
***************
*** 0 ****
--- 1,40 ----
+ /* Decimal floating point support for GDB.
+
+ Copyright 2006 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+ /* Decimal floating point is one of the extension to IEEE 754, which is
+ described in http://grouper.ieee.org/groups/754/revision.html and
+ http://www2.hursley.ibm.com/decimal/. It completes binary floating
+ point by representing floating point more exactly. */
+
+ /* There is a project intended to add DFP support into GCC, described in
+ http://gcc.gnu.org/wiki/Decimal%20Floating-Point. This file is intended
+ to add DFP support into GDB. */
+
+ #ifndef DFP_H
+ #define DFP_H
+ #include <string.h>
+ #include <stdio.h>
+ #include <stdint.h>
+
+ extern void decimal_to_string (const uint8_t *, int, char *);
+ extern int decimal_from_string (uint8_t *, int, char *);
+
+ #endif
Index: dfp.c
===================================================================
RCS file: dfp.c
diff -N dfp.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- dfp.c 1 Aug 2006 10:30:18 -0000
***************
*** 0 ****
--- 1,122 ----
+ /* Decimal floating point support for GDB.
+
+ Copyright 2006 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+ #include "defs.h"
+ #include "dfp.h"
+ #include <ctype.h>
+
+ /* The order of the following headers is important for making sure
+ decNumber structure is large enough to hold decimal128 digits. */
+
+ #include "decimal128.h"
+ #include "decimal64.h"
+ #include "decimal32.h"
+ #include "decNumber.h"
+
+ /* In gdb, we are using an array of gdb_byte to represent decimal
values. The
+ byte order of our representation might be different than that of
underlying
+ architecture. This routine does the conversion if it is necessary. */
+ static void
+ exchange_dfp (const gdb_byte *valaddr, int len, gdb_byte *dec_val)
+ {
+ int index;
+
+ if (gdbarch_byte_order (current_gdbarch) == 1)
+ for (index = 0; index < len; index++)
+ dec_val[index] = valaddr[len - index - 1];
+ else
+ for (index = 0; index < len; index++)
+ dec_val[index] = valaddr[index];
+
+ return;
+ }
+
+ /* Convert deciaml type to its string representation. LEN is the length
+ of the decimal type, 4 bytes for decimal32, 8 bytes for decimal64 and
+ 16 bytes for decimal128. */
+ void
+ decimal_to_string (const uint8_t *decbytes, int len, char *s)
+ {
+ uint8_t *dec = (uint8_t *)malloc (len);
+
+ exchange_dfp (decbytes, len, dec);
+ switch (len)
+ {
+ case 4:
+ decimal32ToString ((decimal32 *) dec, s);
+ return;
+ case 8:
+ decimal64ToString ((decimal64 *) dec, s);
+ return;
+ case 16:
+ decimal128ToString ((decimal128 *) dec, s);
+ return;
+ default:
+ return;
+ }
+
+ free (dec);
+ }
+
+ /* Convert the string form of a decimal value to its decimal representation.
+ LEN is the length of the decimal type, 4 bytes for decimal32, 8 bytes for
+ decimal64 and 16 bytes for decimal128. */
+ int
+ decimal_from_string (uint8_t *decbytes, int len, char *string)
+ {
+ decNumber dn;
+ decContext set;
+ int index;
+ uint8_t *dec = (uint8_t *)malloc (len);
+
+ switch (len)
+ {
+ case 4:
+ decContextDefault (&set, DEC_INIT_DECIMAL32);
+ break;
+ case 8:
+ decContextDefault (&set, DEC_INIT_DECIMAL64);
+ break;
+ case 16:
+ decContextDefault (&set, DEC_INIT_DECIMAL128);
+ break;
+ }
+
+ set.traps = 0;
+
+ decNumberFromString (&dn, string, &set);
+ switch (len)
+ {
+ case 4:
+ decimal32FromNumber ((decimal32 *) dec, &dn, &set);
+ break;
+ case 8:
+ decimal64FromNumber ((decimal64 *) dec, &dn, &set);
+ break;
+ case 16:
+ decimal128FromNumber ((decimal128 *) dec, &dn, &set);
+ break;
+ }
+
+ exchange_dfp (dec, len, decbytes);
+ free (dec);
+ return 1;
+ }
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.834
diff -c -3 -p -r1.834 Makefile.in
*** Makefile.in 31 Jul 2006 20:15:50 -0000 1.834
--- Makefile.in 1 Aug 2006 10:30:18 -0000
*************** BFD = $(BFD_DIR)/libbfd.a
*** 122,127 ****
--- 122,133 ----
BFD_SRC = $(srcdir)/$(BFD_DIR)
BFD_CFLAGS = -I$(BFD_DIR) -I$(BFD_SRC)

+ # Where is the decnumber library? Typically in ../libdecnumber.
+ LIBDECNUMBER_DIR = ../libdecnumber
+ LIBDECNUMBER = $(LIBDECNUMBER_DIR)/libdecnumber.a
+ LIBDECNUMBER_SRC = $(srcdir)/$(LIBDECNUMBER_DIR)
+ LIBDECNUMBER_CFLAGS = -I$(LIBDECNUMBER_DIR) -I$(LIBDECNUMBER_SRC)
+
# Where is the READLINE library? Typically in ../readline.
READLINE_DIR = ../readline
READLINE = $(READLINE_DIR)/libreadline.a
*************** CXXFLAGS = -g -O
*** 348,354 ****
INTERNAL_CFLAGS_BASE = \
$(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \
$(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) \
! $(BFD_CFLAGS) $(INCLUDE_CFLAGS) \
$(INTL_CFLAGS) $(ENABLE_CFLAGS)
INTERNAL_WARN_CFLAGS = $(INTERNAL_CFLAGS_BASE) $(GDB_WARN_CFLAGS)
INTERNAL_CFLAGS = $(INTERNAL_WARN_CFLAGS) $(GDB_WERROR_CFLAGS)
--- 354,360 ----
INTERNAL_CFLAGS_BASE = \
$(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \
$(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) \
! $(BFD_CFLAGS) $(INCLUDE_CFLAGS) $(LIBDECNUMBER_CFLAGS) \
$(INTL_CFLAGS) $(ENABLE_CFLAGS)
INTERNAL_WARN_CFLAGS = $(INTERNAL_CFLAGS_BASE) $(GDB_WARN_CFLAGS)
INTERNAL_CFLAGS = $(INTERNAL_WARN_CFLAGS) $(GDB_WERROR_CFLAGS)
*************** INTERNAL_LDFLAGS = $(CFLAGS) $(GLOBAL_CF
*** 371,380 ****
# LIBIBERTY appears twice on purpose.
# If you have the Cygnus libraries installed,
# you can use 'CLIBS=$(INSTALLED_LIBS)' 'CDEPS='
! INSTALLED_LIBS=-lbfd -lreadline -lopcodes -liberty \
$(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \
-lintl -liberty
! CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(INTL) $(LIBIBERTY) \
$(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \
$(LIBICONV) \
$(LIBIBERTY) $(WIN32LIBS)
--- 377,386 ----
# LIBIBERTY appears twice on purpose.
# If you have the Cygnus libraries installed,
# you can use 'CLIBS=$(INSTALLED_LIBS)' 'CDEPS='
! INSTALLED_LIBS=-lbfd -lreadline -lopcodes -liberty -ldecnumber \
$(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \
-lintl -liberty
! CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(INTL) $(LIBIBERTY)
$(LIBDECNUMBER) \
$(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \
$(LIBICONV) \
$(LIBIBERTY) $(WIN32LIBS)
*************** splay_tree_h = $(INCLUDE_DIR)/splay-tre
*** 604,609 ****
--- 610,619 ----
safe_ctype_h = $(INCLUDE_DIR)/safe-ctype.h
hashtab_h = $(INCLUDE_DIR)/hashtab.h

+ decimal128_h = $(LIBDECNUMBER_DIR)/decimal128.h
+ decimal64_h = $(LIBDECNUMBER_DIR)/decimal64.h
+ decimal32_h = $(LIBDECNUMBER_DIR)/decimal32.h
+
#
# $BUILD/ headers
#
*************** dictionary_h = dictionary.h
*** 670,675 ****
--- 680,686 ----
disasm_h = disasm.h
doublest_h = doublest.h $(floatformat_h)
dummy_frame_h = dummy-frame.h
+ dfp_h = dfp.h
dwarf2expr_h = dwarf2expr.h
dwarf2_frame_h = dwarf2-frame.h
dwarf2loc_h = dwarf2loc.h
*************** COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
*** 911,917 ****
auxv.o \
bfd-target.o \
blockframe.o breakpoint.o findvar.o regcache.o \
! charset.o disasm.o dummy-frame.o \
source.o value.o eval.o valops.o valarith.o valprint.o printcmd.o \
block.o symtab.o symfile.o symmisc.o linespec.o dictionary.o \
infcall.o \
--- 922,928 ----
auxv.o \
bfd-target.o \
blockframe.o breakpoint.o findvar.o regcache.o \
! charset.o disasm.o dummy-frame.o dfp.o \
source.o value.o eval.o valops.o valarith.o valprint.o printcmd.o \
block.o symtab.o symfile.o symmisc.o linespec.o dictionary.o \
infcall.o \
*************** dsrec.o: dsrec.c $(defs_h) $(serial_h) $
*** 1922,1927 ****
--- 1933,1939 ----
dummy-frame.o: dummy-frame.c $(defs_h) $(dummy_frame_h) $(regcache_h) \
$(frame_h) $(inferior_h) $(gdb_assert_h) $(frame_unwind_h) \
$(command_h) $(gdbcmd_h) $(gdb_string_h)
+ dfp.o: dfp.c $(defs_h) $(dfp_h) $(decimal128_h) $(decimal64_h)
$(decimal32_h)
dve3900-rom.o: dve3900-rom.c $(defs_h) $(gdbcore_h) $(target_h)
$(monitor_h) \
$(serial_h) $(inferior_h) $(command_h) $(gdb_string_h) $(regcache_h) \
$(mips_tdep_h)
*************** valops.o: valops.c $(defs_h) $(symtab_h)
*** 2792,2798 ****
valprint.o: valprint.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) $(language_h) \
$(annotate_h) $(valprint_h) $(floatformat_h) $(doublest_h) \
! $(exceptions_h)
value.o: value.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(gdbcore_h) $(command_h) $(gdbcmd_h) $(target_h) \
$(language_h) $(scm_lang_h) $(demangle_h) $(doublest_h) \
--- 2804,2810 ----
valprint.o: valprint.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) $(language_h) \
$(annotate_h) $(valprint_h) $(floatformat_h) $(doublest_h) \
! $(exceptions_h) $(dfp_h)
value.o: value.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(gdbcore_h) $(command_h) $(gdbcmd_h) $(target_h) \
$(language_h) $(scm_lang_h) $(demangle_h) $(doublest_h) \

Quoting Wu Zhou <woodzltc@cn.ibm.com>:

> Hi Daniel,
>
> Thanks for your comment.
>
> Quoting Daniel Jacobowitz <drow@false.org>:
>
>> On Sun, Jul 23, 2006 at 01:47:58AM -0400, Wu Zhou wrote:
>>> My point is to keep these usage so as they are consistent with how
>>> flaot/double is handled. What is your idea on this?
>>
>> I think it would be more useful to search for all reference to decimal
>> float, than it would be to exactly parallel the float/double support.
>
> OK. I will buy your point. :-) The revised patch adopt this preference.
>
>>> But in big-endian machine, this might be not needed. I will try a test
>>> on ppc64.
>
> I made some modification to my patch. It now works on both x86
> (little endian) and ppc64 (big endian) platforms. All 125 tests pass
> on these two platforms. I didn't do any test on cross-debugging though.
>
> Here are some explanation to my revised patch, wishing that it can
> clarfiy the situation somehow.
>
> I am now still use array of bytes (gdb_byte val[16]) to represent
> decimal float in gdb. The reason is that we can't assume that the
> gdb-building compiler supports the decimal extension to C language
> standard. If we can, that will be much easier, we can just use that to
> represent decimal float in gdb.
>
> The order of these bytes are now big-endian, i.e. the first byte is
> the most significant one. But it is maken to be the same as the
> endianess of the target through routine exchange_dfp (in dfp.c). If
> the target is big-endian, no reversion is needed; if it is
> little-endian, reversion is needed. This is done through the checking
> of gdbarch_byte_order (current_gdbarch):
>
> static void
> exchange_dfp (const gdb_byte *valaddr, int len, gdb_byte *dec_val)
> {
> int index;
>
> if (gdbarch_byte_order (current_gdbarch) == 1)
> for (index = 0; index < len; index++)
> dec_val[index] = valaddr[len - index - 1];
> else
> for (index = 0; index < len; index++)
> dec_val[index] = valaddr[index];
>
> return;
> }
>
> Maybe this can't support cross-debugging (I am not sure though). But
> I am planning to take this into consideration. I have one question
> first: which data structure is used to describe the host's byte-order
> information? Anyone is kind to tell me?
>
> Attached below is the revised patch. Please review and comment.
> Thanks a lot!

Regards
- Wu Zhou