03bc1e1e923918ce46569556e3fff816a87c6beb
[deliverable/binutils-gdb.git] / gdb / valarith.c
1 /* Perform arithmetic and other operations on values, for GDB.
2 Copyright (C) 1986 Free Software Foundation, Inc.
3
4 GDB is distributed in the hope that it will be useful, but WITHOUT ANY
5 WARRANTY. No author or distributor accepts responsibility to anyone
6 for the consequences of using it or for whether it serves any
7 particular purpose or works at all, unless he says so in writing.
8 Refer to the GDB General Public License for full details.
9
10 Everyone is granted permission to copy, modify and redistribute GDB,
11 but only under the conditions described in the GDB General Public
12 License. A copy of this license is supposed to have been given to you
13 along with GDB so you can know your rights and responsibilities. It
14 should be in a file named COPYING. Among other things, the copyright
15 notice and this notice must be preserved on all copies.
16
17 In other words, go ahead and share GDB, but don't try to stop
18 anyone else from sharing it farther. Help stamp out software hoarding!
19 */
20
21 #include "defs.h"
22 #include "initialize.h"
23 #include "param.h"
24 #include "symtab.h"
25 #include "value.h"
26 #include "expression.h"
27
28 START_FILE
29 \f
30 value
31 value_add (arg1, arg2)
32 value arg1, arg2;
33 {
34 register value val, valint, valptr;
35 register int len;
36
37 COERCE_ARRAY (arg1);
38 COERCE_ARRAY (arg2);
39
40 if ((TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
41 || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_PTR)
42 &&
43 (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT
44 || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT))
45 /* Exactly one argument is a pointer, and one is an integer. */
46 {
47 if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR)
48 {
49 valptr = arg1;
50 valint = arg2;
51 }
52 else
53 {
54 valptr = arg2;
55 valint = arg1;
56 }
57 len = TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (valptr)));
58 if (len == 0) len = 1; /* For (void *) */
59 val = value_from_long (builtin_type_long,
60 value_as_long (valptr)
61 + (len * value_as_long (valint)));
62 VALUE_TYPE (val) = VALUE_TYPE (valptr);
63 return val;
64 }
65
66 return value_binop (arg1, arg2, BINOP_ADD);
67 }
68
69 value
70 value_sub (arg1, arg2)
71 value arg1, arg2;
72 {
73 register value val;
74
75 COERCE_ARRAY (arg1);
76 COERCE_ARRAY (arg2);
77
78 if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
79 &&
80 TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT)
81 {
82 val = value_from_long (builtin_type_long,
83 value_as_long (arg1)
84 - TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) * value_as_long (arg2));
85 VALUE_TYPE (val) = VALUE_TYPE (arg1);
86 return val;
87 }
88
89 if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
90 &&
91 VALUE_TYPE (arg1) == VALUE_TYPE (arg2))
92 {
93 val = value_from_long (builtin_type_long,
94 (value_as_long (arg1) - value_as_long (arg2))
95 / TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))));
96 return val;
97 }
98
99 return value_binop (arg1, arg2, BINOP_SUB);
100 }
101
102 /* Return the value of ARRAY[IDX]. */
103
104 value
105 value_subscript (array, idx)
106 value array, idx;
107 {
108 return value_ind (value_add (array, idx));
109 }
110
111 /* Perform a binary operation on two integers or two floats.
112 Does not support addition and subtraction on pointers;
113 use value_add or value_sub if you want to handle those possibilities. */
114
115 value
116 value_binop (arg1, arg2, op)
117 value arg1, arg2;
118 int op;
119 {
120 register value val;
121
122 COERCE_ENUM (arg1);
123 COERCE_ENUM (arg2);
124
125 if ((TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_FLT
126 &&
127 TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT)
128 ||
129 (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_FLT
130 &&
131 TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT))
132 error ("Argument to arithmetic operation not a number.");
133
134 if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_FLT
135 ||
136 TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_FLT)
137 {
138 double v1, v2, v;
139 v1 = value_as_double (arg1);
140 v2 = value_as_double (arg2);
141 switch (op)
142 {
143 case BINOP_ADD:
144 v = v1 + v2;
145 break;
146
147 case BINOP_SUB:
148 v = v1 - v2;
149 break;
150
151 case BINOP_MUL:
152 v = v1 * v2;
153 break;
154
155 case BINOP_DIV:
156 v = v1 / v2;
157 break;
158
159 default:
160 error ("Integer-only operation on floating point number.");
161 }
162
163 val = allocate_value (builtin_type_double);
164 *(double *) VALUE_CONTENTS (val) = v;
165 }
166 else
167 {
168 long v1, v2, v;
169 v1 = value_as_long (arg1);
170 v2 = value_as_long (arg2);
171
172 switch (op)
173 {
174 case BINOP_ADD:
175 v = v1 + v2;
176 break;
177
178 case BINOP_SUB:
179 v = v1 - v2;
180 break;
181
182 case BINOP_MUL:
183 v = v1 * v2;
184 break;
185
186 case BINOP_DIV:
187 v = v1 / v2;
188 break;
189
190 case BINOP_REM:
191 v = v1 % v2;
192 break;
193
194 case BINOP_LSH:
195 v = v1 << v2;
196 break;
197
198 case BINOP_RSH:
199 v = v1 >> v2;
200 break;
201
202 case BINOP_LOGAND:
203 v = v1 & v2;
204 break;
205
206 case BINOP_LOGIOR:
207 v = v1 | v2;
208 break;
209
210 case BINOP_LOGXOR:
211 v = v1 ^ v2;
212 break;
213
214 case BINOP_AND:
215 v = v1 && v2;
216 break;
217
218 case BINOP_OR:
219 v = v1 || v2;
220 break;
221
222 default:
223 error ("Invalid binary operation on numbers.");
224 }
225
226 val = allocate_value (builtin_type_long);
227 *(long *) VALUE_CONTENTS (val) = v;
228 }
229
230 return val;
231 }
232 \f
233 /* Simulate the C operator ! -- return 1 if ARG1 contains zeros. */
234
235 int
236 value_zerop (arg1)
237 value arg1;
238 {
239 register int len;
240 register char *p;
241
242 COERCE_ARRAY (arg1);
243
244 len = TYPE_LENGTH (VALUE_TYPE (arg1));
245 p = VALUE_CONTENTS (arg1);
246
247 while (--len >= 0)
248 {
249 if (*p++)
250 break;
251 }
252
253 return len < 0;
254 }
255
256 /* Simulate the C operator == by returning a 1
257 iff ARG1 and ARG2 have equal contents. */
258
259 int
260 value_equal (arg1, arg2)
261 register value arg1, arg2;
262
263 {
264 register int len;
265 register char *p1, *p2;
266 enum type_code code1;
267 enum type_code code2;
268
269 COERCE_ARRAY (arg1);
270 COERCE_ARRAY (arg2);
271
272 code1 = TYPE_CODE (VALUE_TYPE (arg1));
273 code2 = TYPE_CODE (VALUE_TYPE (arg2));
274
275 if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT)
276 return value_as_long (arg1) == value_as_long (arg2);
277 else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
278 && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
279 return value_as_double (arg1) == value_as_double (arg2);
280 else if ((code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_INT)
281 || (code2 == TYPE_CODE_PTR && code1 == TYPE_CODE_INT))
282 return value_as_long (arg1) == value_as_long (arg2);
283 else if (code1 == code2
284 && ((len = TYPE_LENGTH (VALUE_TYPE (arg1)))
285 == TYPE_LENGTH (VALUE_TYPE (arg2))))
286 {
287 p1 = VALUE_CONTENTS (arg1);
288 p2 = VALUE_CONTENTS (arg2);
289 while (--len >= 0)
290 {
291 if (*p1++ != *p2++)
292 break;
293 }
294 return len < 0;
295 }
296 else
297 error ("Invalid type combination in equality test.");
298 }
299
300 /* Simulate the C operator < by returning 1
301 iff ARG1's contents are less than ARG2's. */
302
303 int
304 value_less (arg1, arg2)
305 register value arg1, arg2;
306 {
307 register enum type_code code1;
308 register enum type_code code2;
309
310 COERCE_ARRAY (arg1);
311 COERCE_ARRAY (arg2);
312
313 code1 = TYPE_CODE (VALUE_TYPE (arg1));
314 code2 = TYPE_CODE (VALUE_TYPE (arg2));
315
316 if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT)
317 return value_as_long (arg1) < value_as_long (arg2);
318 else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
319 && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
320 return value_as_double (arg1) < value_as_double (arg2);
321 else if ((code1 == TYPE_CODE_PTR || code1 == TYPE_CODE_INT)
322 && (code2 == TYPE_CODE_PTR || code2 == TYPE_CODE_INT))
323 return value_as_long (arg1) < value_as_long (arg2);
324 else
325 error ("Invalid type combination in ordering comparison.");
326 }
327 \f
328 /* The unary operators - and ~. Both free the argument ARG1. */
329
330 value
331 value_neg (arg1)
332 register value arg1;
333 {
334 register struct type *type;
335
336 COERCE_ENUM (arg1);
337
338 type = VALUE_TYPE (arg1);
339
340 if (TYPE_CODE (type) == TYPE_CODE_FLT)
341 return value_from_double (type, - value_as_double (arg1));
342 else if (TYPE_CODE (type) == TYPE_CODE_INT)
343 return value_from_long (type, - value_as_long (arg1));
344 else
345 error ("Argument to negate operation not a number.");
346 }
347
348 value
349 value_lognot (arg1)
350 register value arg1;
351 {
352 COERCE_ENUM (arg1);
353
354 if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT)
355 error ("Argument to complement operation not an integer.");
356
357 return value_from_long (VALUE_TYPE (arg1), ~ value_as_long (arg1));
358 }
359 \f
360 static
361 initialize ()
362 {
363 }
364
365 END_FILE
This page took 0.035968 seconds and 4 git commands to generate.