ad04f8fb4a195f77572ba2702f6868d3451be11f
[deliverable/binutils-gdb.git] / gdb / target-float.c
1 /* Floating point routines for GDB, the GNU debugger.
2
3 Copyright (C) 2017 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "defs.h"
21 #include "dfp.h"
22 #include "doublest.h"
23 #include "gdbtypes.h"
24 #include "floatformat.h"
25 #include "target-float.h"
26
27
28 /* Helper routines operating on binary floating-point data. */
29
30 #include <math.h>
31
32 /* Convert the byte-stream ADDR, interpreted as floating-point format FMT,
33 to an integer value (rounding towards zero). */
34 static LONGEST
35 floatformat_to_longest (const struct floatformat *fmt, const gdb_byte *addr)
36 {
37 DOUBLEST d;
38 floatformat_to_doublest (fmt, addr, &d);
39 return (LONGEST) d;
40 }
41
42 /* Convert signed integer VAL to a target floating-number of format FMT
43 and store it as byte-stream ADDR. */
44 static void
45 floatformat_from_longest (const struct floatformat *fmt, gdb_byte *addr,
46 LONGEST val)
47 {
48 DOUBLEST d = (DOUBLEST) val;
49 floatformat_from_doublest (fmt, &d, addr);
50 }
51
52 /* Convert unsigned integer VAL to a target floating-number of format FMT
53 and store it as byte-stream ADDR. */
54 static void
55 floatformat_from_ulongest (const struct floatformat *fmt, gdb_byte *addr,
56 ULONGEST val)
57 {
58 DOUBLEST d = (DOUBLEST) val;
59 floatformat_from_doublest (fmt, &d, addr);
60 }
61
62 /* Convert a floating-point number of format FROM_FMT from the target
63 byte-stream FROM to a floating-point number of format TO_FMT, and
64 store it to the target byte-stream TO. */
65 static void
66 floatformat_convert (const gdb_byte *from, const struct floatformat *from_fmt,
67 gdb_byte *to, const struct floatformat *to_fmt)
68 {
69 if (from_fmt == to_fmt)
70 {
71 /* The floating-point formats match, so we simply copy the data. */
72 memcpy (to, from, floatformat_totalsize_bytes (to_fmt));
73 }
74 else
75 {
76 /* The floating-point formats don't match. The best we can do
77 (apart from simulating the target FPU) is converting to the
78 widest floating-point type supported by the host, and then
79 again to the desired type. */
80 DOUBLEST d;
81
82 floatformat_to_doublest (from_fmt, from, &d);
83 floatformat_from_doublest (to_fmt, &d, to);
84 }
85 }
86
87 /* Perform the binary operation indicated by OPCODE, using as operands the
88 target byte streams X and Y, interpreted as floating-point numbers of
89 formats FMT_X and FMT_Y, respectively. Convert the result to format
90 FMT_RES and store it into the byte-stream RES. */
91 static void
92 floatformat_binop (enum exp_opcode op,
93 const struct floatformat *fmt_x, const gdb_byte *x,
94 const struct floatformat *fmt_y, const gdb_byte *y,
95 const struct floatformat *fmt_result, gdb_byte *result)
96 {
97 DOUBLEST v1, v2, v = 0;
98
99 floatformat_to_doublest (fmt_x, x, &v1);
100 floatformat_to_doublest (fmt_y, y, &v2);
101
102 switch (op)
103 {
104 case BINOP_ADD:
105 v = v1 + v2;
106 break;
107
108 case BINOP_SUB:
109 v = v1 - v2;
110 break;
111
112 case BINOP_MUL:
113 v = v1 * v2;
114 break;
115
116 case BINOP_DIV:
117 v = v1 / v2;
118 break;
119
120 case BINOP_EXP:
121 errno = 0;
122 v = pow (v1, v2);
123 if (errno)
124 error (_("Cannot perform exponentiation: %s"),
125 safe_strerror (errno));
126 break;
127
128 case BINOP_MIN:
129 v = v1 < v2 ? v1 : v2;
130 break;
131
132 case BINOP_MAX:
133 v = v1 > v2 ? v1 : v2;
134 break;
135
136 default:
137 error (_("Integer-only operation on floating point number."));
138 break;
139 }
140
141 floatformat_from_doublest (fmt_result, &v, result);
142 }
143
144 /* Compare the two target byte streams X and Y, interpreted as floating-point
145 numbers of formats FMT_X and FMT_Y, respectively. Return zero if X and Y
146 are equal, -1 if X is less than Y, and 1 otherwise. */
147 static int
148 floatformat_compare (const struct floatformat *fmt_x, const gdb_byte *x,
149 const struct floatformat *fmt_y, const gdb_byte *y)
150 {
151 DOUBLEST v1, v2;
152
153 floatformat_to_doublest (fmt_x, x, &v1);
154 floatformat_to_doublest (fmt_y, y, &v2);
155
156 if (v1 == v2)
157 return 0;
158 if (v1 < v2)
159 return -1;
160 return 1;
161 }
162
163
164 /* Typed floating-point routines. These routines operate on floating-point
165 values in target format, represented by a byte buffer interpreted as a
166 "struct type", which may be either a binary or decimal floating-point
167 type (TYPE_CODE_FLT or TYPE_CODE_DECFLOAT). */
168
169 /* Return whether the byte-stream ADDR holds a valid value of
170 floating-point type TYPE. */
171 bool
172 target_float_is_valid (const gdb_byte *addr, const struct type *type)
173 {
174 if (TYPE_CODE (type) == TYPE_CODE_FLT)
175 return floatformat_is_valid (floatformat_from_type (type), addr);
176
177 if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
178 return true;
179
180 gdb_assert_not_reached ("unexpected type code");
181 }
182
183 /* Return whether the byte-stream ADDR, interpreted as floating-point
184 type TYPE, is numerically equal to zero (of either sign). */
185 bool
186 target_float_is_zero (const gdb_byte *addr, const struct type *type)
187 {
188 if (TYPE_CODE (type) == TYPE_CODE_FLT)
189 return (floatformat_classify (floatformat_from_type (type), addr)
190 == float_zero);
191
192 if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
193 return decimal_is_zero (addr, TYPE_LENGTH (type),
194 gdbarch_byte_order (get_type_arch (type)));
195
196 gdb_assert_not_reached ("unexpected type code");
197 }
198
199 /* Convert the byte-stream ADDR, interpreted as floating-point type TYPE,
200 to a string, optionally using the print format FORMAT. */
201 std::string
202 target_float_to_string (const gdb_byte *addr, const struct type *type,
203 const char *format)
204 {
205 if (TYPE_CODE (type) == TYPE_CODE_FLT)
206 return floatformat_to_string (floatformat_from_type (type), addr, format);
207
208 if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
209 return decimal_to_string (addr, TYPE_LENGTH (type),
210 gdbarch_byte_order (get_type_arch (type)),
211 format);
212
213 gdb_assert_not_reached ("unexpected type code");
214 }
215
216 /* Parse string STRING into a target floating-number of type TYPE and
217 store it as byte-stream ADDR. Return whether parsing succeeded. */
218 bool
219 target_float_from_string (gdb_byte *addr, const struct type *type,
220 const std::string &string)
221 {
222 /* Ensure possible padding bytes in the target buffer are zeroed out. */
223 memset (addr, 0, TYPE_LENGTH (type));
224
225 if (TYPE_CODE (type) == TYPE_CODE_FLT)
226 return floatformat_from_string (floatformat_from_type (type), addr,
227 string);
228
229 if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
230 return decimal_from_string (addr, TYPE_LENGTH (type),
231 gdbarch_byte_order (get_type_arch (type)),
232 string);
233
234 gdb_assert_not_reached ("unexpected type code");
235 }
236
237 /* Convert the byte-stream ADDR, interpreted as floating-point type TYPE,
238 to an integer value (rounding towards zero). */
239 LONGEST
240 target_float_to_longest (const gdb_byte *addr, const struct type *type)
241 {
242 if (TYPE_CODE (type) == TYPE_CODE_FLT)
243 return floatformat_to_longest (floatformat_from_type (type), addr);
244
245 if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
246 return decimal_to_longest (addr, TYPE_LENGTH (type),
247 gdbarch_byte_order (get_type_arch (type)));
248
249 gdb_assert_not_reached ("unexpected type code");
250 }
251
252 /* Convert signed integer VAL to a target floating-number of type TYPE
253 and store it as byte-stream ADDR. */
254 void
255 target_float_from_longest (gdb_byte *addr, const struct type *type,
256 LONGEST val)
257 {
258 /* Ensure possible padding bytes in the target buffer are zeroed out. */
259 memset (addr, 0, TYPE_LENGTH (type));
260
261 if (TYPE_CODE (type) == TYPE_CODE_FLT)
262 {
263 floatformat_from_longest (floatformat_from_type (type), addr, val);
264 return;
265 }
266
267 if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
268 {
269 decimal_from_longest (val, addr, TYPE_LENGTH (type),
270 gdbarch_byte_order (get_type_arch (type)));
271 return;
272 }
273
274 gdb_assert_not_reached ("unexpected type code");
275 }
276
277 /* Convert unsigned integer VAL to a target floating-number of type TYPE
278 and store it as byte-stream ADDR. */
279 void
280 target_float_from_ulongest (gdb_byte *addr, const struct type *type,
281 ULONGEST val)
282 {
283 /* Ensure possible padding bytes in the target buffer are zeroed out. */
284 memset (addr, 0, TYPE_LENGTH (type));
285
286 if (TYPE_CODE (type) == TYPE_CODE_FLT)
287 {
288 floatformat_from_ulongest (floatformat_from_type (type), addr, val);
289 return;
290 }
291
292 if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
293 {
294 decimal_from_ulongest (val, addr, TYPE_LENGTH (type),
295 gdbarch_byte_order (get_type_arch (type)));
296 return;
297 }
298
299 gdb_assert_not_reached ("unexpected type code");
300 }
301
302 /* Convert a floating-point number of type FROM_TYPE from the target
303 byte-stream FROM to a floating-point number of type TO_TYPE, and
304 store it to the target byte-stream TO. */
305 void
306 target_float_convert (const gdb_byte *from, const struct type *from_type,
307 gdb_byte *to, const struct type *to_type)
308 {
309 /* Ensure possible padding bytes in the target buffer are zeroed out. */
310 memset (to, 0, TYPE_LENGTH (to_type));
311
312 /* Use direct conversion routines if we have them. */
313
314 if (TYPE_CODE (from_type) == TYPE_CODE_FLT
315 && TYPE_CODE (to_type) == TYPE_CODE_FLT)
316 {
317 floatformat_convert (from, floatformat_from_type (from_type),
318 to, floatformat_from_type (to_type));
319 return;
320 }
321
322 if (TYPE_CODE (from_type) == TYPE_CODE_DECFLOAT
323 && TYPE_CODE (to_type) == TYPE_CODE_DECFLOAT)
324 {
325 decimal_convert (from, TYPE_LENGTH (from_type),
326 gdbarch_byte_order (get_type_arch (from_type)),
327 to, TYPE_LENGTH (to_type),
328 gdbarch_byte_order (get_type_arch (to_type)));
329 return;
330 }
331
332 /* We cannot directly convert between binary and decimal floating-point
333 types, so go via an intermediary string. */
334
335 if ((TYPE_CODE (from_type) == TYPE_CODE_FLT
336 && TYPE_CODE (to_type) == TYPE_CODE_DECFLOAT)
337 || (TYPE_CODE (from_type) == TYPE_CODE_DECFLOAT
338 && TYPE_CODE (to_type) == TYPE_CODE_FLT))
339 {
340 std::string str = target_float_to_string (from, from_type);
341 target_float_from_string (to, to_type, str);
342 return;
343 }
344
345 gdb_assert_not_reached ("unexpected type code");
346 }
347
348 /* Perform the binary operation indicated by OPCODE, using as operands the
349 target byte streams X and Y, interpreted as floating-point numbers of
350 types TYPE_X and TYPE_Y, respectively. Convert the result to type
351 TYPE_RES and store it into the byte-stream RES.
352
353 The three types must either be all binary floating-point types, or else
354 all decimal floating-point types. Binary and decimal floating-point
355 types cannot be mixed within a single operation. */
356 void
357 target_float_binop (enum exp_opcode opcode,
358 const gdb_byte *x, const struct type *type_x,
359 const gdb_byte *y, const struct type *type_y,
360 gdb_byte *res, const struct type *type_res)
361 {
362 /* Ensure possible padding bytes in the target buffer are zeroed out. */
363 memset (res, 0, TYPE_LENGTH (type_res));
364
365 if (TYPE_CODE (type_res) == TYPE_CODE_FLT)
366 {
367 gdb_assert (TYPE_CODE (type_x) == TYPE_CODE_FLT);
368 gdb_assert (TYPE_CODE (type_y) == TYPE_CODE_FLT);
369 return floatformat_binop (opcode,
370 floatformat_from_type (type_x), x,
371 floatformat_from_type (type_y), y,
372 floatformat_from_type (type_res), res);
373 }
374
375 if (TYPE_CODE (type_res) == TYPE_CODE_DECFLOAT)
376 {
377 gdb_assert (TYPE_CODE (type_x) == TYPE_CODE_DECFLOAT);
378 gdb_assert (TYPE_CODE (type_y) == TYPE_CODE_DECFLOAT);
379 return decimal_binop (opcode,
380 x, TYPE_LENGTH (type_x),
381 gdbarch_byte_order (get_type_arch (type_x)),
382 y, TYPE_LENGTH (type_y),
383 gdbarch_byte_order (get_type_arch (type_y)),
384 res, TYPE_LENGTH (type_res),
385 gdbarch_byte_order (get_type_arch (type_res)));
386 }
387
388 gdb_assert_not_reached ("unexpected type code");
389 }
390
391 /* Compare the two target byte streams X and Y, interpreted as floating-point
392 numbers of types TYPE_X and TYPE_Y, respectively. Return zero if X and Y
393 are equal, -1 if X is less than Y, and 1 otherwise.
394
395 The two types must either both be binary floating-point types, or else
396 both be decimal floating-point types. Binary and decimal floating-point
397 types cannot compared directly against each other. */
398 int
399 target_float_compare (const gdb_byte *x, const struct type *type_x,
400 const gdb_byte *y, const struct type *type_y)
401 {
402 if (TYPE_CODE (type_x) == TYPE_CODE_FLT)
403 {
404 gdb_assert (TYPE_CODE (type_y) == TYPE_CODE_FLT);
405 return floatformat_compare (floatformat_from_type (type_x), x,
406 floatformat_from_type (type_y), y);
407 }
408
409 if (TYPE_CODE (type_x) == TYPE_CODE_DECFLOAT)
410 {
411 gdb_assert (TYPE_CODE (type_y) == TYPE_CODE_DECFLOAT);
412 return decimal_compare (x, TYPE_LENGTH (type_x),
413 gdbarch_byte_order (get_type_arch (type_x)),
414 y, TYPE_LENGTH (type_y),
415 gdbarch_byte_order (get_type_arch (type_y)));
416 }
417
418 gdb_assert_not_reached ("unexpected type code");
419 }
420
This page took 0.037753 seconds and 4 git commands to generate.