* i387-tdep.c (print_i387_value): Use extract_typed_floating to
[deliverable/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 #if GDB_MULTI_ARCH >0
34 #include "i386-tdep.h"
35 #endif
36
37 /* FIXME: Eliminate the next two functions when we have the time to
38 change all the callers. */
39
40 void i387_to_double (char *from, char *to);
41 void double_to_i387 (char *from, char *to);
42
43 void
44 i387_to_double (char *from, char *to)
45 {
46 floatformat_to_double (&floatformat_i387_ext, from, (double *) to);
47 }
48
49 void
50 double_to_i387 (char *from, char *to)
51 {
52 floatformat_from_double (&floatformat_i387_ext, (double *) from, to);
53 }
54
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
62 static void print_387_control_bits (unsigned int control);
63 static void print_387_status_bits (unsigned int status);
64
65 static void
66 print_387_control_bits (unsigned int control)
67 {
68 switch ((control >> 8) & 3)
69 {
70 case 0:
71 puts_unfiltered (" 24 bit; ");
72 break;
73 case 1:
74 puts_unfiltered (" (bad); ");
75 break;
76 case 2:
77 puts_unfiltered (" 53 bit; ");
78 break;
79 case 3:
80 puts_unfiltered (" 64 bit; ");
81 break;
82 }
83 switch ((control >> 10) & 3)
84 {
85 case 0:
86 puts_unfiltered ("NEAR; ");
87 break;
88 case 1:
89 puts_unfiltered ("DOWN; ");
90 break;
91 case 2:
92 puts_unfiltered ("UP; ");
93 break;
94 case 3:
95 puts_unfiltered ("CHOP; ");
96 break;
97 }
98 if (control & 0x3f)
99 {
100 puts_unfiltered ("mask");
101 if (control & 0x0001)
102 puts_unfiltered (" INVAL");
103 if (control & 0x0002)
104 puts_unfiltered (" DENOR");
105 if (control & 0x0004)
106 puts_unfiltered (" DIVZ");
107 if (control & 0x0008)
108 puts_unfiltered (" OVERF");
109 if (control & 0x0010)
110 puts_unfiltered (" UNDER");
111 if (control & 0x0020)
112 puts_unfiltered (" LOS");
113 puts_unfiltered (";");
114 }
115
116 if (control & 0xe080)
117 warning ("\nreserved bits on: %s",
118 local_hex_string (control & 0xe080));
119 }
120
121 void
122 print_387_control_word (unsigned int control)
123 {
124 printf_filtered ("control %s:", local_hex_string(control & 0xffff));
125 print_387_control_bits (control);
126 puts_unfiltered ("\n");
127 }
128
129 static void
130 print_387_status_bits (unsigned int status)
131 {
132 printf_unfiltered (" flags %d%d%d%d; ",
133 (status & 0x4000) != 0,
134 (status & 0x0400) != 0,
135 (status & 0x0200) != 0,
136 (status & 0x0100) != 0);
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
151 void
152 print_387_status_word (unsigned int status)
153 {
154 printf_filtered ("status %s:", local_hex_string (status & 0xffff));
155 print_387_status_bits (status);
156 puts_unfiltered ("\n");
157 }
158
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. */
164 static void
165 print_i387_value (char *raw)
166 {
167 DOUBLEST value;
168
169 /* Using extract_typed_floating here might affect the representation
170 of certain numbers such as NaNs, even if GDB is running natively.
171 This is fine since our caller already detects such special
172 numbers and we print the hexadecimal representation anyway. */
173 value = extract_typed_floating (raw, builtin_type_i387_ext);
174
175 /* We try to print 19 digits. The last digit may or may not contain
176 garbage, but we'd better print one too many. We need enough room
177 to print the value, 1 position for the sign, 1 for the decimal
178 point, 19 for the digits and 6 for the exponent adds up to 27. */
179 #ifdef PRINTF_HAS_LONG_DOUBLE
180 printf_filtered (" %-+27.19Lg", (long double) value);
181 #else
182 printf_filtered (" %-+27.19g", (double) value);
183 #endif
184 }
185
186 /* Print the classification for the register contents RAW. */
187 static void
188 print_i387_ext (unsigned char *raw)
189 {
190 int sign;
191 int integer;
192 unsigned int exponent;
193 unsigned long fraction[2];
194
195 sign = raw[9] & 0x80;
196 integer = raw[7] & 0x80;
197 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
198 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
199 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
200 | (raw[5] << 8) | raw[4]);
201
202 if (exponent == 0x7fff && integer)
203 {
204 if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
205 /* Infinity. */
206 printf_filtered (" %cInf", (sign ? '-' : '+'));
207 else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
208 /* Real Indefinite (QNaN). */
209 puts_unfiltered (" Real Indefinite (QNaN)");
210 else if (fraction[1] & 0x40000000)
211 /* QNaN. */
212 puts_filtered (" QNaN");
213 else
214 /* SNaN. */
215 puts_filtered (" SNaN");
216 }
217 else if (exponent < 0x7fff && exponent > 0x0000 && integer)
218 /* Normal. */
219 print_i387_value (raw);
220 else if (exponent == 0x0000)
221 {
222 /* Denormal or zero. */
223 print_i387_value (raw);
224
225 if (integer)
226 /* Pseudo-denormal. */
227 puts_filtered (" Pseudo-denormal");
228 else if (fraction[0] || fraction[1])
229 /* Denormal. */
230 puts_filtered (" Denormal");
231 }
232 else
233 /* Unsupported. */
234 puts_filtered (" Unsupported");
235 }
236
237 /* Print the status word STATUS. */
238 static void
239 print_i387_status_word (unsigned int status)
240 {
241 printf_filtered ("Status Word: %s",
242 local_hex_string_custom (status, "04"));
243 puts_filtered (" ");
244 printf_filtered (" %s", (status & 0x0001) ? "IE" : " ");
245 printf_filtered (" %s", (status & 0x0002) ? "DE" : " ");
246 printf_filtered (" %s", (status & 0x0004) ? "ZE" : " ");
247 printf_filtered (" %s", (status & 0x0008) ? "OE" : " ");
248 printf_filtered (" %s", (status & 0x0010) ? "UE" : " ");
249 printf_filtered (" %s", (status & 0x0020) ? "PE" : " ");
250 puts_filtered (" ");
251 printf_filtered (" %s", (status & 0x0080) ? "ES" : " ");
252 puts_filtered (" ");
253 printf_filtered (" %s", (status & 0x0040) ? "SF" : " ");
254 puts_filtered (" ");
255 printf_filtered (" %s", (status & 0x0100) ? "C0" : " ");
256 printf_filtered (" %s", (status & 0x0200) ? "C1" : " ");
257 printf_filtered (" %s", (status & 0x0400) ? "C2" : " ");
258 printf_filtered (" %s", (status & 0x4000) ? "C3" : " ");
259
260 puts_filtered ("\n");
261
262 printf_filtered (" TOP: %d\n", ((status >> 11) & 7));
263 }
264
265 /* Print the control word CONTROL. */
266 static void
267 print_i387_control_word (unsigned int control)
268 {
269 printf_filtered ("Control Word: %s",
270 local_hex_string_custom (control, "04"));
271 puts_filtered (" ");
272 printf_filtered (" %s", (control & 0x0001) ? "IM" : " ");
273 printf_filtered (" %s", (control & 0x0002) ? "DM" : " ");
274 printf_filtered (" %s", (control & 0x0004) ? "ZM" : " ");
275 printf_filtered (" %s", (control & 0x0008) ? "OM" : " ");
276 printf_filtered (" %s", (control & 0x0010) ? "UM" : " ");
277 printf_filtered (" %s", (control & 0x0020) ? "PM" : " ");
278
279 puts_filtered ("\n");
280
281 puts_filtered (" PC: ");
282 switch ((control >> 8) & 3)
283 {
284 case 0:
285 puts_filtered ("Single Precision (24-bits)\n");
286 break;
287 case 1:
288 puts_filtered ("Reserved\n");
289 break;
290 case 2:
291 puts_filtered ("Double Precision (53-bits)\n");
292 break;
293 case 3:
294 puts_filtered ("Extended Precision (64-bits)\n");
295 break;
296 }
297
298 puts_filtered (" RC: ");
299 switch ((control >> 10) & 3)
300 {
301 case 0:
302 puts_filtered ("Round to nearest\n");
303 break;
304 case 1:
305 puts_filtered ("Round down\n");
306 break;
307 case 2:
308 puts_filtered ("Round up\n");
309 break;
310 case 3:
311 puts_filtered ("Round toward zero\n");
312 break;
313 }
314 }
315
316 /* Print out the i387 floating poin state. */
317 void
318 i387_float_info (void)
319 {
320 unsigned int fctrl;
321 unsigned int fstat;
322 unsigned int ftag;
323 unsigned int fiseg;
324 unsigned int fioff;
325 unsigned int foseg;
326 unsigned int fooff;
327 unsigned int fop;
328 int fpreg;
329 int top;
330
331 fctrl = read_register (FCTRL_REGNUM);
332 fstat = read_register (FSTAT_REGNUM);
333 ftag = read_register (FTAG_REGNUM);
334 fiseg = read_register (FCS_REGNUM);
335 fioff = read_register (FCOFF_REGNUM);
336 foseg = read_register (FDS_REGNUM);
337 fooff = read_register (FDOFF_REGNUM);
338 fop = read_register (FOP_REGNUM);
339
340 top = ((fstat >> 11) & 7);
341
342 for (fpreg = 7; fpreg >= 0; fpreg--)
343 {
344 unsigned char raw[FPU_REG_RAW_SIZE];
345 int tag = (ftag >> (fpreg * 2)) & 3;
346 int i;
347
348 printf_filtered ("%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
349
350 switch (tag)
351 {
352 case 0:
353 puts_filtered ("Valid ");
354 break;
355 case 1:
356 puts_filtered ("Zero ");
357 break;
358 case 2:
359 puts_filtered ("Special ");
360 break;
361 case 3:
362 puts_filtered ("Empty ");
363 break;
364 }
365
366 read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
367
368 puts_filtered ("0x");
369 for (i = 9; i >= 0; i--)
370 printf_filtered ("%02x", raw[i]);
371
372 if (tag != 3)
373 print_i387_ext (raw);
374
375 puts_filtered ("\n");
376 }
377
378 puts_filtered ("\n");
379
380 print_i387_status_word (fstat);
381 print_i387_control_word (fctrl);
382 printf_filtered ("Tag Word: %s\n",
383 local_hex_string_custom (ftag, "04"));
384 printf_filtered ("Instruction Pointer: %s:",
385 local_hex_string_custom (fiseg, "02"));
386 printf_filtered ("%s\n", local_hex_string_custom (fioff, "08"));
387 printf_filtered ("Operand Pointer: %s:",
388 local_hex_string_custom (foseg, "02"));
389 printf_filtered ("%s\n", local_hex_string_custom (fooff, "08"));
390 printf_filtered ("Opcode: %s\n",
391 local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
392 }
This page took 0.042882 seconds and 5 git commands to generate.