]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/i387-tdep.c
* gdbtypes.c (_initialize_gdbtypes): Set floating-point type for
[thirdparty/binutils-gdb.git] / gdb / i387-tdep.c
CommitLineData
c906108c 1/* Intel 387 floating point stuff.
b6ba6518
KB
2 Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
c906108c 4
c5aa993b 5 This file is part of GDB.
c906108c 6
c5aa993b
JM
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 2 of the License, or
10 (at your option) any later version.
c906108c 11
c5aa993b
JM
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.
c906108c 16
c5aa993b
JM
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
c906108c
SS
21
22#include "defs.h"
23#include "frame.h"
24#include "inferior.h"
25#include "language.h"
d4f3574e 26#include "value.h"
c906108c
SS
27#include "gdbcore.h"
28#include "floatformat.h"
4e052eda 29#include "regcache.h"
d0df8472 30#include "gdb_assert.h"
d16aafd8 31#include "doublest.h"
c906108c 32
9a82579f
JS
33#if GDB_MULTI_ARCH >0
34#include "i386-tdep.h"
35#endif
c906108c 36
de57eccd
JM
37/* FIXME: Eliminate the next two functions when we have the time to
38 change all the callers. */
d4f3574e 39
a14ed312
KB
40void i387_to_double (char *from, char *to);
41void double_to_i387 (char *from, char *to);
c906108c
SS
42
43void
fba45db2 44i387_to_double (char *from, char *to)
c906108c 45{
c5aa993b 46 floatformat_to_double (&floatformat_i387_ext, from, (double *) to);
c906108c
SS
47}
48
49void
fba45db2 50double_to_i387 (char *from, char *to)
c906108c 51{
c5aa993b 52 floatformat_from_double (&floatformat_i387_ext, (double *) from, to);
c906108c
SS
53}
54
de57eccd
JM
55\f
56/* FIXME: The functions on this page are used by the old `info float'
57 implementations that a few of the i386 targets provide. These
58 functions should be removed if all of these have been converted to
59 use the generic implementation based on the new register file
60 layout. */
61
a14ed312
KB
62static void print_387_control_bits (unsigned int control);
63static void print_387_status_bits (unsigned int status);
de57eccd 64
d4f3574e 65static void
fba45db2 66print_387_control_bits (unsigned int control)
c906108c 67{
c5aa993b 68 switch ((control >> 8) & 3)
c906108c 69 {
c5aa993b 70 case 0:
d4f3574e 71 puts_unfiltered (" 24 bit; ");
c5aa993b
JM
72 break;
73 case 1:
d4f3574e 74 puts_unfiltered (" (bad); ");
c5aa993b
JM
75 break;
76 case 2:
d4f3574e 77 puts_unfiltered (" 53 bit; ");
c5aa993b
JM
78 break;
79 case 3:
d4f3574e 80 puts_unfiltered (" 64 bit; ");
c5aa993b 81 break;
c906108c 82 }
c5aa993b 83 switch ((control >> 10) & 3)
c906108c 84 {
c5aa993b 85 case 0:
d4f3574e 86 puts_unfiltered ("NEAR; ");
c5aa993b
JM
87 break;
88 case 1:
d4f3574e 89 puts_unfiltered ("DOWN; ");
c5aa993b
JM
90 break;
91 case 2:
d4f3574e 92 puts_unfiltered ("UP; ");
c5aa993b
JM
93 break;
94 case 3:
d4f3574e 95 puts_unfiltered ("CHOP; ");
c5aa993b 96 break;
c906108c 97 }
c5aa993b 98 if (control & 0x3f)
c906108c 99 {
d4f3574e 100 puts_unfiltered ("mask");
c5aa993b 101 if (control & 0x0001)
d4f3574e 102 puts_unfiltered (" INVAL");
c5aa993b 103 if (control & 0x0002)
d4f3574e 104 puts_unfiltered (" DENOR");
c5aa993b 105 if (control & 0x0004)
d4f3574e 106 puts_unfiltered (" DIVZ");
c5aa993b 107 if (control & 0x0008)
d4f3574e 108 puts_unfiltered (" OVERF");
c5aa993b 109 if (control & 0x0010)
d4f3574e 110 puts_unfiltered (" UNDER");
c5aa993b 111 if (control & 0x0020)
d4f3574e
SS
112 puts_unfiltered (" LOS");
113 puts_unfiltered (";");
c906108c 114 }
cff3e48b 115
c5aa993b 116 if (control & 0xe080)
d4f3574e 117 warning ("\nreserved bits on: %s",
c5aa993b 118 local_hex_string (control & 0xe080));
c906108c
SS
119}
120
121void
fba45db2 122print_387_control_word (unsigned int control)
d4f3574e
SS
123{
124 printf_filtered ("control %s:", local_hex_string(control & 0xffff));
125 print_387_control_bits (control);
126 puts_unfiltered ("\n");
127}
128
129static void
fba45db2 130print_387_status_bits (unsigned int status)
c906108c 131{
d4f3574e 132 printf_unfiltered (" flags %d%d%d%d; ",
c5aa993b
JM
133 (status & 0x4000) != 0,
134 (status & 0x0400) != 0,
135 (status & 0x0200) != 0,
136 (status & 0x0100) != 0);
d4f3574e
SS
137 printf_unfiltered ("top %d; ", (status >> 11) & 7);
138 if (status & 0xff)
139 {
140 puts_unfiltered ("excep");
141 if (status & 0x0001) puts_unfiltered (" INVAL");
142 if (status & 0x0002) puts_unfiltered (" DENOR");
143 if (status & 0x0004) puts_unfiltered (" DIVZ");
144 if (status & 0x0008) puts_unfiltered (" OVERF");
145 if (status & 0x0010) puts_unfiltered (" UNDER");
146 if (status & 0x0020) puts_unfiltered (" LOS");
147 if (status & 0x0040) puts_unfiltered (" STACK");
148 }
149}
150
151void
fba45db2 152print_387_status_word (unsigned int status)
d4f3574e
SS
153{
154 printf_filtered ("status %s:", local_hex_string (status & 0xffff));
155 print_387_status_bits (status);
156 puts_unfiltered ("\n");
157}
158
de57eccd
JM
159\f
160/* Implement the `info float' layout based on the register definitions
161 in `tm-i386.h'. */
162
163/* Print the floating point number specified by RAW. */
164static void
165print_i387_value (char *raw)
166{
167 DOUBLEST value;
d0df8472
AC
168 int len = TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT;
169 char *tmp = alloca (len);
170
171 /* This code only works on targets where ... */
172 gdb_assert (TARGET_LONG_DOUBLE_FORMAT == &floatformat_i387_ext);
173
174 /* Take care of the padding. FP reg is 80 bits. The same value in
c96646d0 175 memory is 96 bits. */
d0df8472 176 gdb_assert (FPU_REG_RAW_SIZE < len);
7f1659e6
MC
177 memcpy (tmp, raw, FPU_REG_RAW_SIZE);
178 memset (tmp + FPU_REG_RAW_SIZE, 0, len - FPU_REG_RAW_SIZE);
d0df8472
AC
179
180 /* Extract the value as a DOUBLEST. */
181 /* Use extract_floating() rather than floatformat_to_doublest().
182 The latter is lossy in nature. Once GDB gets a host/target
183 independent and non-lossy FP it will become possible to bypass
184 extract_floating() and call floatformat*() directly. Note also
185 the assumptions about TARGET_LONG_DOUBLE above. */
186 value = extract_floating (tmp, len);
de57eccd
JM
187
188 /* We try to print 19 digits. The last digit may or may not contain
189 garbage, but we'd better print one too many. We need enough room
190 to print the value, 1 position for the sign, 1 for the decimal
191 point, 19 for the digits and 6 for the exponent adds up to 27. */
192#ifdef PRINTF_HAS_LONG_DOUBLE
193 printf_filtered (" %-+27.19Lg", (long double) value);
194#else
195 printf_filtered (" %-+27.19g", (double) value);
196#endif
197}
198
199/* Print the classification for the register contents RAW. */
200static void
201print_i387_ext (unsigned char *raw)
202{
203 int sign;
204 int integer;
205 unsigned int exponent;
206 unsigned long fraction[2];
207
208 sign = raw[9] & 0x80;
209 integer = raw[7] & 0x80;
210 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
211 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
212 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
213 | (raw[5] << 8) | raw[4]);
214
215 if (exponent == 0x7fff && integer)
216 {
217 if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
218 /* Infinity. */
219 printf_filtered (" %cInf", (sign ? '-' : '+'));
220 else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
221 /* Real Indefinite (QNaN). */
222 puts_unfiltered (" Real Indefinite (QNaN)");
223 else if (fraction[1] & 0x40000000)
224 /* QNaN. */
225 puts_filtered (" QNaN");
226 else
227 /* SNaN. */
228 puts_filtered (" SNaN");
229 }
230 else if (exponent < 0x7fff && exponent > 0x0000 && integer)
231 /* Normal. */
232 print_i387_value (raw);
233 else if (exponent == 0x0000)
234 {
235 /* Denormal or zero. */
236 print_i387_value (raw);
237
238 if (integer)
239 /* Pseudo-denormal. */
240 puts_filtered (" Pseudo-denormal");
241 else if (fraction[0] || fraction[1])
242 /* Denormal. */
243 puts_filtered (" Denormal");
244 }
245 else
246 /* Unsupported. */
247 puts_filtered (" Unsupported");
248}
249
250/* Print the status word STATUS. */
251static void
252print_i387_status_word (unsigned int status)
253{
254 printf_filtered ("Status Word: %s",
255 local_hex_string_custom (status, "04"));
256 puts_filtered (" ");
257 printf_filtered (" %s", (status & 0x0001) ? "IE" : " ");
258 printf_filtered (" %s", (status & 0x0002) ? "DE" : " ");
259 printf_filtered (" %s", (status & 0x0004) ? "ZE" : " ");
260 printf_filtered (" %s", (status & 0x0008) ? "OE" : " ");
261 printf_filtered (" %s", (status & 0x0010) ? "UE" : " ");
262 printf_filtered (" %s", (status & 0x0020) ? "PE" : " ");
263 puts_filtered (" ");
264 printf_filtered (" %s", (status & 0x0080) ? "ES" : " ");
265 puts_filtered (" ");
96836138 266 printf_filtered (" %s", (status & 0x0040) ? "SF" : " ");
de57eccd
JM
267 puts_filtered (" ");
268 printf_filtered (" %s", (status & 0x0100) ? "C0" : " ");
269 printf_filtered (" %s", (status & 0x0200) ? "C1" : " ");
270 printf_filtered (" %s", (status & 0x0400) ? "C2" : " ");
271 printf_filtered (" %s", (status & 0x4000) ? "C3" : " ");
272
273 puts_filtered ("\n");
274
275 printf_filtered (" TOP: %d\n", ((status >> 11) & 7));
276}
277
278/* Print the control word CONTROL. */
279static void
280print_i387_control_word (unsigned int control)
281{
282 printf_filtered ("Control Word: %s",
283 local_hex_string_custom (control, "04"));
284 puts_filtered (" ");
285 printf_filtered (" %s", (control & 0x0001) ? "IM" : " ");
286 printf_filtered (" %s", (control & 0x0002) ? "DM" : " ");
287 printf_filtered (" %s", (control & 0x0004) ? "ZM" : " ");
288 printf_filtered (" %s", (control & 0x0008) ? "OM" : " ");
289 printf_filtered (" %s", (control & 0x0010) ? "UM" : " ");
290 printf_filtered (" %s", (control & 0x0020) ? "PM" : " ");
291
292 puts_filtered ("\n");
293
294 puts_filtered (" PC: ");
295 switch ((control >> 8) & 3)
296 {
297 case 0:
298 puts_filtered ("Single Precision (24-bits)\n");
299 break;
300 case 1:
301 puts_filtered ("Reserved\n");
302 break;
303 case 2:
304 puts_filtered ("Double Precision (53-bits)\n");
305 break;
306 case 3:
307 puts_filtered ("Extended Precision (64-bits)\n");
308 break;
309 }
310
311 puts_filtered (" RC: ");
312 switch ((control >> 10) & 3)
313 {
314 case 0:
315 puts_filtered ("Round to nearest\n");
316 break;
317 case 1:
318 puts_filtered ("Round down\n");
319 break;
320 case 2:
321 puts_filtered ("Round up\n");
322 break;
323 case 3:
324 puts_filtered ("Round toward zero\n");
325 break;
326 }
327}
328
329/* Print out the i387 floating poin state. */
330void
331i387_float_info (void)
332{
333 unsigned int fctrl;
334 unsigned int fstat;
335 unsigned int ftag;
336 unsigned int fiseg;
337 unsigned int fioff;
338 unsigned int foseg;
339 unsigned int fooff;
340 unsigned int fop;
341 int fpreg;
342 int top;
343
344 fctrl = read_register (FCTRL_REGNUM);
345 fstat = read_register (FSTAT_REGNUM);
346 ftag = read_register (FTAG_REGNUM);
347 fiseg = read_register (FCS_REGNUM);
348 fioff = read_register (FCOFF_REGNUM);
349 foseg = read_register (FDS_REGNUM);
350 fooff = read_register (FDOFF_REGNUM);
351 fop = read_register (FOP_REGNUM);
352
353 top = ((fstat >> 11) & 7);
354
355 for (fpreg = 7; fpreg >= 0; fpreg--)
356 {
357 unsigned char raw[FPU_REG_RAW_SIZE];
358 int tag = (ftag >> (fpreg * 2)) & 3;
359 int i;
360
361 printf_filtered ("%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
362
363 switch (tag)
364 {
365 case 0:
366 puts_filtered ("Valid ");
367 break;
368 case 1:
369 puts_filtered ("Zero ");
370 break;
371 case 2:
372 puts_filtered ("Special ");
373 break;
374 case 3:
375 puts_filtered ("Empty ");
376 break;
377 }
378
379 read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
380
381 puts_filtered ("0x");
382 for (i = 9; i >= 0; i--)
383 printf_filtered ("%02x", raw[i]);
384
385 if (tag != 3)
386 print_i387_ext (raw);
387
388 puts_filtered ("\n");
389 }
390
391 puts_filtered ("\n");
392
393 print_i387_status_word (fstat);
394 print_i387_control_word (fctrl);
395 printf_filtered ("Tag Word: %s\n",
396 local_hex_string_custom (ftag, "04"));
397 printf_filtered ("Instruction Pointer: %s:",
398 local_hex_string_custom (fiseg, "02"));
399 printf_filtered ("%s\n", local_hex_string_custom (fioff, "08"));
400 printf_filtered ("Operand Pointer: %s:",
401 local_hex_string_custom (foseg, "02"));
402 printf_filtered ("%s\n", local_hex_string_custom (fooff, "08"));
403 printf_filtered ("Opcode: %s\n",
404 local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
405}