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