aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog25
-rw-r--r--gdb/c-exp.y47
-rw-r--r--gdb/eval.c5
-rw-r--r--gdb/expression.h6
-rw-r--r--gdb/parse.c13
-rw-r--r--gdb/parser-defs.h2
-rw-r--r--gdb/valarith.c17
-rw-r--r--gdb/value.c22
-rw-r--r--gdb/value.h3
9 files changed, 140 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index be6eab8..f86576c 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,6 +1,31 @@
2007-10-25 Wu Zhou <woodzltc@cn.ibm.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
+ * c-exp.y (YYSTYPE): Add typed_val_decfloat for decimal
+ floating point in YYSTYPE union.
+ (DECFLOAT) Add token and expression element handling code.
+ (parse_number): Parse DFP constants, which end with suffix 'df',
+ 'dd' or 'dl'. Return DECFLOAT.
+ * eval.c (evaluate_subexp_standard): Call value_from_decfloat to
+ handle OP_DECFLOAT.
+ * 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.
+ * 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.
+ * parser-defs.h (write_exp_elt_decfloatcst): Prototype.
+ * valarith.c (value_neg): Add code to handle the negation
+ operation of DFP values.
+ * value.c (value_from_decfloat): New function to get the value
+ from a decimal floating point.
+ * value.h (value_from_decfloat): Prototype.
+
+2007-10-25 Wu Zhou <woodzltc@cn.ibm.com>
+ Thiago Jung Bauermann <bauerman@br.ibm.com>
+
* c-lang.c (c_create_fundamental_type): Create fundamental
types for DFP.
* c-typeprint.c (c_type_print_varspec_prefix): Add
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 6318955..40dbc93 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -52,6 +52,7 @@ Boston, MA 02110-1301, USA. */
#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
@@ -130,6 +131,10 @@ void yyerror (char *);
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;
@@ -162,6 +167,7 @@ static int parse_number (char *, int, int, YYSTYPE *);
%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.
@@ -496,6 +502,13 @@ exp : FLOAT
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
;
@@ -1077,6 +1090,40 @@ parse_number (p, len, parsed_float, putithere)
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 */
diff --git a/gdb/eval.c b/gdb/eval.c
index ee1ac58..2e6a832 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -456,6 +456,11 @@ evaluate_subexp_standard (struct type *expect_type,
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)
diff --git a/gdb/expression.h b/gdb/expression.h
index fb4ecac..01ddc05 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -328,6 +328,11 @@ enum exp_opcode
/* 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
@@ -355,6 +360,7 @@ union exp_element
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;
diff --git a/gdb/parse.c b/gdb/parse.c
index 9303dfd..8841e59 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -248,6 +248,18 @@ write_exp_elt_dblcst (DOUBLEST expelt)
}
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;
@@ -718,6 +730,7 @@ operator_length_standard (struct expression *expr, int endpos,
case OP_LONG:
case OP_DOUBLE:
+ case OP_DECFLOAT:
case OP_VAR_VALUE:
oplen = 4;
break;
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index 417bc5b..7928537 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -119,6 +119,8 @@ extern void write_exp_elt_longcst (LONGEST);
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 *);
diff --git a/gdb/valarith.c b/gdb/valarith.c
index ed65d66..9771ac8 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -1376,6 +1376,23 @@ value_neg (struct value *arg1)
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[16]; /* a decfloat is at most 128 bits long */
+
+ memcpy(decbytes, value_contents(arg1), len);
+
+ if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_LITTLE)
+ decbytes[len-1] = decbytes[len - 1] | 0x80;
+ else
+ decbytes[0] = decbytes[0] | 0x80;
+
+ memcpy (value_contents_raw (val), decbytes, len);
+ 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))
diff --git a/gdb/value.c b/gdb/value.c
index 7085ec1..89759b8 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -34,6 +34,7 @@
#include "gdb_assert.h"
#include "regcache.h"
#include "block.h"
+#include "dfp.h"
/* Prototypes for exported functions. */
@@ -1642,6 +1643,27 @@ value_from_double (struct type *type, DOUBLEST num)
}
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));
diff --git a/gdb/value.h b/gdb/value.h
index 7026466..ada7fc7 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -280,6 +280,9 @@ extern void pack_long (gdb_byte *buf, struct type *type, LONGEST num);
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);