diff options
Diffstat (limited to 'gdb/valarith.c')
-rw-r--r-- | gdb/valarith.c | 330 |
1 files changed, 238 insertions, 92 deletions
diff --git a/gdb/valarith.c b/gdb/valarith.c index 772e590..ac3f0f4 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -1,22 +1,21 @@ /* Perform arithmetic and other operations on values, for GDB. - Copyright (C) 1986 Free Software Foundation, Inc. + Copyright (C) 1986, 1989 Free Software Foundation, Inc. -GDB is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY. No author or distributor accepts responsibility to anyone -for the consequences of using it or for whether it serves any -particular purpose or works at all, unless he says so in writing. -Refer to the GDB General Public License for full details. +This file is part of GDB. -Everyone is granted permission to copy, modify and redistribute GDB, -but only under the conditions described in the GDB General Public -License. A copy of this license is supposed to have been given to you -along with GDB so you can know your rights and responsibilities. It -should be in a file named COPYING. Among other things, the copyright -notice and this notice must be preserved on all copies. +GDB 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 1, or (at your option) +any later version. -In other words, go ahead and share GDB, but don't try to stop -anyone else from sharing it farther. Help stamp out software hoarding! -*/ +GDB 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 GDB; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" #include "param.h" @@ -26,6 +25,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! value value_x_binop (); +value value_subscripted_rvalue (); value value_add (arg1, arg2) @@ -105,7 +105,58 @@ value value_subscript (array, idx) value array, idx; { - return value_ind (value_add (array, idx)); + if (TYPE_CODE (VALUE_TYPE (array)) == TYPE_CODE_ARRAY + && VALUE_LVAL (array) != lval_memory) + return value_subscripted_rvalue (array, idx); + else + return value_ind (value_add (array, idx)); +} + +/* Return the value of EXPR[IDX], expr an aggregate rvalue + (eg, a vector register) */ + +value +value_subscripted_rvalue (array, idx) + value array, idx; +{ + struct type *elt_type = TYPE_TARGET_TYPE (VALUE_TYPE (array)); + int elt_size = TYPE_LENGTH (elt_type); + int elt_offs = elt_size * value_as_long (idx); + value v; + + if (elt_offs >= TYPE_LENGTH (VALUE_TYPE (array))) + error ("no such vector element"); + + if (TYPE_CODE (elt_type) == TYPE_CODE_FLT) + { + if (elt_size == sizeof (float)) + v = value_from_double (elt_type, (double) *(float *) + (VALUE_CONTENTS (array) + elt_offs)); + else + v = value_from_double (elt_type, *(double *) + (VALUE_CONTENTS (array) + elt_offs)); + } + else + { + int offs; + union {int i; char c;} test; + test.i = 1; + if (test.c == 1) + offs = 0; + else + offs = sizeof (LONGEST) - elt_size; + v = value_from_long (elt_type, *(LONGEST *) + (VALUE_CONTENTS (array) + elt_offs - offs)); + } + + if (VALUE_LVAL (array) == lval_internalvar) + VALUE_LVAL (v) = lval_internalvar_component; + else + VALUE_LVAL (v) = not_lval; + VALUE_ADDRESS (v) = VALUE_ADDRESS (array); + VALUE_OFFSET (v) = VALUE_OFFSET (array) + elt_offs; + VALUE_BITSIZE (v) = elt_size * 8; + return v; } /* Check to see if either argument is a structure. This is called so @@ -159,7 +210,8 @@ value_x_binop (arg1, arg2, op, otherop) value * argvec; char *ptr; char tstr[13]; - + int static_memfuncp; + COERCE_ENUM (arg1); COERCE_ENUM (arg2); @@ -219,10 +271,17 @@ value_x_binop (arg1, arg2, op, otherop) default: error ("Invalid binary operation specified."); } - argvec[0] = value_struct_elt (arg1, argvec+1, tstr, "structure"); + argvec[0] = value_struct_elt (arg1, argvec+1, tstr, &static_memfuncp, "structure"); if (argvec[0]) - return call_function (argvec[0], 2, argvec + 1); - else error ("member function %s not found", tstr); + { + if (static_memfuncp) + { + argvec[1] = argvec[0]; + argvec++; + } + return call_function (argvec[0], 2 - static_memfuncp, argvec + 1); + } + error ("member function %s not found", tstr); } /* We know that arg1 is a structure, so try to find a unary user @@ -239,7 +298,8 @@ value_x_unop (arg1, op) value * argvec; char *ptr; char tstr[13]; - + int static_memfuncp; + COERCE_ENUM (arg1); /* now we know that what we have to do is construct our @@ -267,10 +327,17 @@ value_x_unop (arg1, op) default: error ("Invalid binary operation specified."); } - argvec[0] = value_struct_elt (arg1, argvec+1, tstr, "structure"); + argvec[0] = value_struct_elt (arg1, argvec+1, tstr, static_memfuncp, "structure"); if (argvec[0]) - return call_function (argvec[0], 1, argvec + 1); - else error ("member function %s not found", tstr); + { + if (static_memfuncp) + { + argvec[1] = argvec[0]; + argvec++; + } + return call_function (argvec[0], 1 - static_memfuncp, argvec + 1); + } + error ("member function %s not found", tstr); } /* Perform a binary operation on two integers or two floats. @@ -329,75 +396,154 @@ value_binop (arg1, arg2, op) *(double *) VALUE_CONTENTS (val) = v; } else + /* Integral operations here. */ { - LONGEST v1, v2, v; - v1 = value_as_long (arg1); - v2 = value_as_long (arg2); - - switch (op) + /* Should we promote to unsigned longest? */ + if ((TYPE_UNSIGNED (VALUE_TYPE (arg1)) + || TYPE_UNSIGNED (VALUE_TYPE (arg2))) + && (TYPE_LENGTH (VALUE_TYPE (arg1)) >= sizeof (unsigned LONGEST) + || TYPE_LENGTH (VALUE_TYPE (arg1)) >= sizeof (unsigned LONGEST))) { - case BINOP_ADD: - v = v1 + v2; - break; - - case BINOP_SUB: - v = v1 - v2; - break; - - case BINOP_MUL: - v = v1 * v2; - break; - - case BINOP_DIV: - v = v1 / v2; - break; - - case BINOP_REM: - v = v1 % v2; - break; - - case BINOP_LSH: - v = v1 << v2; - break; - - case BINOP_RSH: - v = v1 >> v2; - break; - - case BINOP_LOGAND: - v = v1 & v2; - break; - - case BINOP_LOGIOR: - v = v1 | v2; - break; - - case BINOP_LOGXOR: - v = v1 ^ v2; - break; - - case BINOP_AND: - v = v1 && v2; - break; - - case BINOP_OR: - v = v1 || v2; - break; - - case BINOP_MIN: - v = v1 < v2 ? v1 : v2; - break; - - case BINOP_MAX: - v = v1 > v2 ? v1 : v2; - break; - - default: - error ("Invalid binary operation on numbers."); + unsigned LONGEST v1, v2, v; + v1 = (unsigned LONGEST) value_as_long (arg1); + v2 = (unsigned LONGEST) value_as_long (arg2); + + switch (op) + { + case BINOP_ADD: + v = v1 + v2; + break; + + case BINOP_SUB: + v = v1 - v2; + break; + + case BINOP_MUL: + v = v1 * v2; + break; + + case BINOP_DIV: + v = v1 / v2; + break; + + case BINOP_REM: + v = v1 % v2; + break; + + case BINOP_LSH: + v = v1 << v2; + break; + + case BINOP_RSH: + v = v1 >> v2; + break; + + case BINOP_LOGAND: + v = v1 & v2; + break; + + case BINOP_LOGIOR: + v = v1 | v2; + break; + + case BINOP_LOGXOR: + v = v1 ^ v2; + break; + + case BINOP_AND: + v = v1 && v2; + break; + + case BINOP_OR: + v = v1 || v2; + break; + + case BINOP_MIN: + v = v1 < v2 ? v1 : v2; + break; + + case BINOP_MAX: + v = v1 > v2 ? v1 : v2; + break; + + default: + error ("Invalid binary operation on numbers."); + } + + val = allocate_value (BUILTIN_TYPE_UNSIGNED_LONGEST); + *(unsigned LONGEST *) VALUE_CONTENTS (val) = v; + } + else + { + LONGEST v1, v2, v; + v1 = value_as_long (arg1); + v2 = value_as_long (arg2); + + switch (op) + { + case BINOP_ADD: + v = v1 + v2; + break; + + case BINOP_SUB: + v = v1 - v2; + break; + + case BINOP_MUL: + v = v1 * v2; + break; + + case BINOP_DIV: + v = v1 / v2; + break; + + case BINOP_REM: + v = v1 % v2; + break; + + case BINOP_LSH: + v = v1 << v2; + break; + + case BINOP_RSH: + v = v1 >> v2; + break; + + case BINOP_LOGAND: + v = v1 & v2; + break; + + case BINOP_LOGIOR: + v = v1 | v2; + break; + + case BINOP_LOGXOR: + v = v1 ^ v2; + break; + + case BINOP_AND: + v = v1 && v2; + break; + + case BINOP_OR: + v = v1 || v2; + break; + + case BINOP_MIN: + v = v1 < v2 ? v1 : v2; + break; + + case BINOP_MAX: + v = v1 > v2 ? v1 : v2; + break; + + default: + error ("Invalid binary operation on numbers."); + } + + val = allocate_value (BUILTIN_TYPE_LONGEST); + *(LONGEST *) VALUE_CONTENTS (val) = v; } - - val = allocate_value (BUILTIN_TYPE_LONGEST); - *(LONGEST *) VALUE_CONTENTS (val) = v; } return val; @@ -452,7 +598,7 @@ value_equal (arg1, arg2) return value_as_double (arg1) == value_as_double (arg2); else if ((code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_INT) || (code2 == TYPE_CODE_PTR && code1 == TYPE_CODE_INT)) - return value_as_long (arg1) == value_as_long (arg2); + return (char *) value_as_long (arg1) == (char *) value_as_long (arg2); else if (code1 == code2 && ((len = TYPE_LENGTH (VALUE_TYPE (arg1))) == TYPE_LENGTH (VALUE_TYPE (arg2)))) @@ -493,7 +639,7 @@ value_less (arg1, arg2) return value_as_double (arg1) < value_as_double (arg2); else if ((code1 == TYPE_CODE_PTR || code1 == TYPE_CODE_INT) && (code2 == TYPE_CODE_PTR || code2 == TYPE_CODE_INT)) - return value_as_long (arg1) < value_as_long (arg2); + return (char *) value_as_long (arg1) < (char *) value_as_long (arg2); else error ("Invalid type combination in ordering comparison."); } |