]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/target-float.c
1 /* Floating point routines for GDB, the GNU debugger.
3 Copyright (C) 2017 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
24 #include "floatformat.h"
25 #include "target-float.h"
28 /* Helper routines operating on binary floating-point data. */
30 /* Convert the byte-stream ADDR, interpreted as floating-point format FMT,
31 to an integer value (rounding towards zero). */
33 floatformat_to_longest (const struct floatformat
*fmt
, const gdb_byte
*addr
)
36 floatformat_to_doublest (fmt
, addr
, &d
);
40 /* Convert signed integer VAL to a target floating-number of format FMT
41 and store it as byte-stream ADDR. */
43 floatformat_from_longest (const struct floatformat
*fmt
, gdb_byte
*addr
,
46 DOUBLEST d
= (DOUBLEST
) val
;
47 floatformat_from_doublest (fmt
, &d
, addr
);
50 /* Convert unsigned integer VAL to a target floating-number of format FMT
51 and store it as byte-stream ADDR. */
53 floatformat_from_ulongest (const struct floatformat
*fmt
, gdb_byte
*addr
,
56 DOUBLEST d
= (DOUBLEST
) val
;
57 floatformat_from_doublest (fmt
, &d
, addr
);
60 /* Convert a floating-point number of format FROM_FMT from the target
61 byte-stream FROM to a floating-point number of format TO_FMT, and
62 store it to the target byte-stream TO. */
64 floatformat_convert (const gdb_byte
*from
, const struct floatformat
*from_fmt
,
65 gdb_byte
*to
, const struct floatformat
*to_fmt
)
67 if (from_fmt
== to_fmt
)
69 /* The floating-point formats match, so we simply copy the data. */
70 memcpy (to
, from
, floatformat_totalsize_bytes (to_fmt
));
74 /* The floating-point formats don't match. The best we can do
75 (apart from simulating the target FPU) is converting to the
76 widest floating-point type supported by the host, and then
77 again to the desired type. */
80 floatformat_to_doublest (from_fmt
, from
, &d
);
81 floatformat_from_doublest (to_fmt
, &d
, to
);
86 /* Typed floating-point routines. These routines operate on floating-point
87 values in target format, represented by a byte buffer interpreted as a
88 "struct type", which may be either a binary or decimal floating-point
89 type (TYPE_CODE_FLT or TYPE_CODE_DECFLOAT). */
91 /* Return whether the byte-stream ADDR holds a valid value of
92 floating-point type TYPE. */
94 target_float_is_valid (const gdb_byte
*addr
, const struct type
*type
)
96 if (TYPE_CODE (type
) == TYPE_CODE_FLT
)
97 return floatformat_is_valid (floatformat_from_type (type
), addr
);
99 if (TYPE_CODE (type
) == TYPE_CODE_DECFLOAT
)
102 gdb_assert_not_reached ("unexpected type code");
105 /* Return whether the byte-stream ADDR, interpreted as floating-point
106 type TYPE, is numerically equal to zero (of either sign). */
108 target_float_is_zero (const gdb_byte
*addr
, const struct type
*type
)
110 if (TYPE_CODE (type
) == TYPE_CODE_FLT
)
111 return (floatformat_classify (floatformat_from_type (type
), addr
)
114 if (TYPE_CODE (type
) == TYPE_CODE_DECFLOAT
)
115 return decimal_is_zero (addr
, TYPE_LENGTH (type
),
116 gdbarch_byte_order (get_type_arch (type
)));
118 gdb_assert_not_reached ("unexpected type code");
121 /* Convert the byte-stream ADDR, interpreted as floating-point type TYPE,
122 to a string, optionally using the print format FORMAT. */
124 target_float_to_string (const gdb_byte
*addr
, const struct type
*type
,
127 if (TYPE_CODE (type
) == TYPE_CODE_FLT
)
128 return floatformat_to_string (floatformat_from_type (type
), addr
, format
);
130 if (TYPE_CODE (type
) == TYPE_CODE_DECFLOAT
)
131 return decimal_to_string (addr
, TYPE_LENGTH (type
),
132 gdbarch_byte_order (get_type_arch (type
)),
135 gdb_assert_not_reached ("unexpected type code");
138 /* Parse string STRING into a target floating-number of type TYPE and
139 store it as byte-stream ADDR. Return whether parsing succeeded. */
141 target_float_from_string (gdb_byte
*addr
, const struct type
*type
,
142 const std::string
&string
)
144 /* Ensure possible padding bytes in the target buffer are zeroed out. */
145 memset (addr
, 0, TYPE_LENGTH (type
));
147 if (TYPE_CODE (type
) == TYPE_CODE_FLT
)
148 return floatformat_from_string (floatformat_from_type (type
), addr
,
151 if (TYPE_CODE (type
) == TYPE_CODE_DECFLOAT
)
152 return decimal_from_string (addr
, TYPE_LENGTH (type
),
153 gdbarch_byte_order (get_type_arch (type
)),
156 gdb_assert_not_reached ("unexpected type code");
159 /* Convert the byte-stream ADDR, interpreted as floating-point type TYPE,
160 to an integer value (rounding towards zero). */
162 target_float_to_longest (const gdb_byte
*addr
, const struct type
*type
)
164 if (TYPE_CODE (type
) == TYPE_CODE_FLT
)
165 return floatformat_to_longest (floatformat_from_type (type
), addr
);
167 if (TYPE_CODE (type
) == TYPE_CODE_DECFLOAT
)
168 return decimal_to_longest (addr
, TYPE_LENGTH (type
),
169 gdbarch_byte_order (get_type_arch (type
)));
171 gdb_assert_not_reached ("unexpected type code");
174 /* Convert signed integer VAL to a target floating-number of type TYPE
175 and store it as byte-stream ADDR. */
177 target_float_from_longest (gdb_byte
*addr
, const struct type
*type
,
180 /* Ensure possible padding bytes in the target buffer are zeroed out. */
181 memset (addr
, 0, TYPE_LENGTH (type
));
183 if (TYPE_CODE (type
) == TYPE_CODE_FLT
)
185 floatformat_from_longest (floatformat_from_type (type
), addr
, val
);
189 if (TYPE_CODE (type
) == TYPE_CODE_DECFLOAT
)
191 decimal_from_longest (val
, addr
, TYPE_LENGTH (type
),
192 gdbarch_byte_order (get_type_arch (type
)));
196 gdb_assert_not_reached ("unexpected type code");
199 /* Convert unsigned integer VAL to a target floating-number of type TYPE
200 and store it as byte-stream ADDR. */
202 target_float_from_ulongest (gdb_byte
*addr
, const struct type
*type
,
205 /* Ensure possible padding bytes in the target buffer are zeroed out. */
206 memset (addr
, 0, TYPE_LENGTH (type
));
208 if (TYPE_CODE (type
) == TYPE_CODE_FLT
)
210 floatformat_from_ulongest (floatformat_from_type (type
), addr
, val
);
214 if (TYPE_CODE (type
) == TYPE_CODE_DECFLOAT
)
216 decimal_from_ulongest (val
, addr
, TYPE_LENGTH (type
),
217 gdbarch_byte_order (get_type_arch (type
)));
221 gdb_assert_not_reached ("unexpected type code");
224 /* Convert a floating-point number of type FROM_TYPE from the target
225 byte-stream FROM to a floating-point number of type TO_TYPE, and
226 store it to the target byte-stream TO. */
228 target_float_convert (const gdb_byte
*from
, const struct type
*from_type
,
229 gdb_byte
*to
, const struct type
*to_type
)
231 /* Ensure possible padding bytes in the target buffer are zeroed out. */
232 memset (to
, 0, TYPE_LENGTH (to_type
));
234 /* Use direct conversion routines if we have them. */
236 if (TYPE_CODE (from_type
) == TYPE_CODE_FLT
237 && TYPE_CODE (to_type
) == TYPE_CODE_FLT
)
239 floatformat_convert (from
, floatformat_from_type (from_type
),
240 to
, floatformat_from_type (to_type
));
244 if (TYPE_CODE (from_type
) == TYPE_CODE_DECFLOAT
245 && TYPE_CODE (to_type
) == TYPE_CODE_DECFLOAT
)
247 decimal_convert (from
, TYPE_LENGTH (from_type
),
248 gdbarch_byte_order (get_type_arch (from_type
)),
249 to
, TYPE_LENGTH (to_type
),
250 gdbarch_byte_order (get_type_arch (to_type
)));
254 /* We cannot directly convert between binary and decimal floating-point
255 types, so go via an intermediary string. */
257 if ((TYPE_CODE (from_type
) == TYPE_CODE_FLT
258 && TYPE_CODE (to_type
) == TYPE_CODE_DECFLOAT
)
259 || (TYPE_CODE (from_type
) == TYPE_CODE_DECFLOAT
260 && TYPE_CODE (to_type
) == TYPE_CODE_FLT
))
262 std::string str
= target_float_to_string (from
, from_type
);
263 target_float_from_string (to
, to_type
, str
);
267 gdb_assert_not_reached ("unexpected type code");