import gdb-1999-12-07 snapshot
[binutils-gdb.git] / gdb / i387-tdep.c
1 /* Intel 387 floating point stuff.
2 Copyright (C) 1988, 1989, 1991, 1998, 1999 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 #include "defs.h"
22 #include "frame.h"
23 #include "inferior.h"
24 #include "language.h"
25 #include "value.h"
26 #include "gdbcore.h"
27 #include "floatformat.h"
28
29
30 /* FIXME: Eliminate the next two functions when we have the time to
31 change all the callers. */
32
33 void i387_to_double PARAMS ((char *from, char *to));
34 void double_to_i387 PARAMS ((char *from, char *to));
35
36 void
37 i387_to_double (from, to)
38 char *from;
39 char *to;
40 {
41 floatformat_to_double (&floatformat_i387_ext, from, (double *) to);
42 }
43
44 void
45 double_to_i387 (from, to)
46 char *from;
47 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 PARAMS ((unsigned int control));
60 static void print_387_status_bits PARAMS ((unsigned int status));
61
62 static void
63 print_387_control_bits (control)
64 unsigned int control;
65 {
66 switch ((control >> 8) & 3)
67 {
68 case 0:
69 puts_unfiltered (" 24 bit; ");
70 break;
71 case 1:
72 puts_unfiltered (" (bad); ");
73 break;
74 case 2:
75 puts_unfiltered (" 53 bit; ");
76 break;
77 case 3:
78 puts_unfiltered (" 64 bit; ");
79 break;
80 }
81 switch ((control >> 10) & 3)
82 {
83 case 0:
84 puts_unfiltered ("NEAR; ");
85 break;
86 case 1:
87 puts_unfiltered ("DOWN; ");
88 break;
89 case 2:
90 puts_unfiltered ("UP; ");
91 break;
92 case 3:
93 puts_unfiltered ("CHOP; ");
94 break;
95 }
96 if (control & 0x3f)
97 {
98 puts_unfiltered ("mask");
99 if (control & 0x0001)
100 puts_unfiltered (" INVAL");
101 if (control & 0x0002)
102 puts_unfiltered (" DENOR");
103 if (control & 0x0004)
104 puts_unfiltered (" DIVZ");
105 if (control & 0x0008)
106 puts_unfiltered (" OVERF");
107 if (control & 0x0010)
108 puts_unfiltered (" UNDER");
109 if (control & 0x0020)
110 puts_unfiltered (" LOS");
111 puts_unfiltered (";");
112 }
113
114 if (control & 0xe080)
115 warning ("\nreserved bits on: %s",
116 local_hex_string (control & 0xe080));
117 }
118
119 void
120 print_387_control_word (control)
121 unsigned int control;
122 {
123 printf_filtered ("control %s:", local_hex_string(control & 0xffff));
124 print_387_control_bits (control);
125 puts_unfiltered ("\n");
126 }
127
128 static void
129 print_387_status_bits (status)
130 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 (status)
153 unsigned int status;
154 {
155 printf_filtered ("status %s:", local_hex_string (status & 0xffff));
156 print_387_status_bits (status);
157 puts_unfiltered ("\n");
158 }
159
160 \f
161 /* Implement the `info float' layout based on the register definitions
162 in `tm-i386.h'. */
163
164 /* Print the floating point number specified by RAW. */
165 static void
166 print_i387_value (char *raw)
167 {
168 DOUBLEST value;
169
170 floatformat_to_doublest (&floatformat_i387_ext, raw, &value);
171
172 /* We try to print 19 digits. The last digit may or may not contain
173 garbage, but we'd better print one too many. We need enough room
174 to print the value, 1 position for the sign, 1 for the decimal
175 point, 19 for the digits and 6 for the exponent adds up to 27. */
176 #ifdef PRINTF_HAS_LONG_DOUBLE
177 printf_filtered (" %-+27.19Lg", (long double) value);
178 #else
179 printf_filtered (" %-+27.19g", (double) value);
180 #endif
181 }
182
183 /* Print the classification for the register contents RAW. */
184 static void
185 print_i387_ext (unsigned char *raw)
186 {
187 int sign;
188 int integer;
189 unsigned int exponent;
190 unsigned long fraction[2];
191
192 sign = raw[9] & 0x80;
193 integer = raw[7] & 0x80;
194 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
195 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
196 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
197 | (raw[5] << 8) | raw[4]);
198
199 if (exponent == 0x7fff && integer)
200 {
201 if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
202 /* Infinity. */
203 printf_filtered (" %cInf", (sign ? '-' : '+'));
204 else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
205 /* Real Indefinite (QNaN). */
206 puts_unfiltered (" Real Indefinite (QNaN)");
207 else if (fraction[1] & 0x40000000)
208 /* QNaN. */
209 puts_filtered (" QNaN");
210 else
211 /* SNaN. */
212 puts_filtered (" SNaN");
213 }
214 else if (exponent < 0x7fff && exponent > 0x0000 && integer)
215 /* Normal. */
216 print_i387_value (raw);
217 else if (exponent == 0x0000)
218 {
219 /* Denormal or zero. */
220 print_i387_value (raw);
221
222 if (integer)
223 /* Pseudo-denormal. */
224 puts_filtered (" Pseudo-denormal");
225 else if (fraction[0] || fraction[1])
226 /* Denormal. */
227 puts_filtered (" Denormal");
228 }
229 else
230 /* Unsupported. */
231 puts_filtered (" Unsupported");
232 }
233
234 /* Print the status word STATUS. */
235 static void
236 print_i387_status_word (unsigned int status)
237 {
238 printf_filtered ("Status Word: %s",
239 local_hex_string_custom (status, "04"));
240 puts_filtered (" ");
241 printf_filtered (" %s", (status & 0x0001) ? "IE" : " ");
242 printf_filtered (" %s", (status & 0x0002) ? "DE" : " ");
243 printf_filtered (" %s", (status & 0x0004) ? "ZE" : " ");
244 printf_filtered (" %s", (status & 0x0008) ? "OE" : " ");
245 printf_filtered (" %s", (status & 0x0010) ? "UE" : " ");
246 printf_filtered (" %s", (status & 0x0020) ? "PE" : " ");
247 puts_filtered (" ");
248 printf_filtered (" %s", (status & 0x0080) ? "ES" : " ");
249 puts_filtered (" ");
250 printf_filtered (" %s", (status & 0x0080) ? "SF" : " ");
251 puts_filtered (" ");
252 printf_filtered (" %s", (status & 0x0100) ? "C0" : " ");
253 printf_filtered (" %s", (status & 0x0200) ? "C1" : " ");
254 printf_filtered (" %s", (status & 0x0400) ? "C2" : " ");
255 printf_filtered (" %s", (status & 0x4000) ? "C3" : " ");
256
257 puts_filtered ("\n");
258
259 printf_filtered (" TOP: %d\n", ((status >> 11) & 7));
260 }
261
262 /* Print the control word CONTROL. */
263 static void
264 print_i387_control_word (unsigned int control)
265 {
266 printf_filtered ("Control Word: %s",
267 local_hex_string_custom (control, "04"));
268 puts_filtered (" ");
269 printf_filtered (" %s", (control & 0x0001) ? "IM" : " ");
270 printf_filtered (" %s", (control & 0x0002) ? "DM" : " ");
271 printf_filtered (" %s", (control & 0x0004) ? "ZM" : " ");
272 printf_filtered (" %s", (control & 0x0008) ? "OM" : " ");
273 printf_filtered (" %s", (control & 0x0010) ? "UM" : " ");
274 printf_filtered (" %s", (control & 0x0020) ? "PM" : " ");
275
276 puts_filtered ("\n");
277
278 puts_filtered (" PC: ");
279 switch ((control >> 8) & 3)
280 {
281 case 0:
282 puts_filtered ("Single Precision (24-bits)\n");
283 break;
284 case 1:
285 puts_filtered ("Reserved\n");
286 break;
287 case 2:
288 puts_filtered ("Double Precision (53-bits)\n");
289 break;
290 case 3:
291 puts_filtered ("Extended Precision (64-bits)\n");
292 break;
293 }
294
295 puts_filtered (" RC: ");
296 switch ((control >> 10) & 3)
297 {
298 case 0:
299 puts_filtered ("Round to nearest\n");
300 break;
301 case 1:
302 puts_filtered ("Round down\n");
303 break;
304 case 2:
305 puts_filtered ("Round up\n");
306 break;
307 case 3:
308 puts_filtered ("Round toward zero\n");
309 break;
310 }
311 }
312
313 /* Print out the i387 floating poin state. */
314 void
315 i387_float_info (void)
316 {
317 unsigned int fctrl;
318 unsigned int fstat;
319 unsigned int ftag;
320 unsigned int fiseg;
321 unsigned int fioff;
322 unsigned int foseg;
323 unsigned int fooff;
324 unsigned int fop;
325 int fpreg;
326 int top;
327
328 fctrl = read_register (FCTRL_REGNUM);
329 fstat = read_register (FSTAT_REGNUM);
330 ftag = read_register (FTAG_REGNUM);
331 fiseg = read_register (FCS_REGNUM);
332 fioff = read_register (FCOFF_REGNUM);
333 foseg = read_register (FDS_REGNUM);
334 fooff = read_register (FDOFF_REGNUM);
335 fop = read_register (FOP_REGNUM);
336
337 top = ((fstat >> 11) & 7);
338
339 for (fpreg = 7; fpreg >= 0; fpreg--)
340 {
341 unsigned char raw[FPU_REG_RAW_SIZE];
342 int tag = (ftag >> (fpreg * 2)) & 3;
343 int i;
344
345 printf_filtered ("%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
346
347 switch (tag)
348 {
349 case 0:
350 puts_filtered ("Valid ");
351 break;
352 case 1:
353 puts_filtered ("Zero ");
354 break;
355 case 2:
356 puts_filtered ("Special ");
357 break;
358 case 3:
359 puts_filtered ("Empty ");
360 break;
361 }
362
363 read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
364
365 puts_filtered ("0x");
366 for (i = 9; i >= 0; i--)
367 printf_filtered ("%02x", raw[i]);
368
369 if (tag != 3)
370 print_i387_ext (raw);
371
372 puts_filtered ("\n");
373 }
374
375 puts_filtered ("\n");
376
377 print_i387_status_word (fstat);
378 print_i387_control_word (fctrl);
379 printf_filtered ("Tag Word: %s\n",
380 local_hex_string_custom (ftag, "04"));
381 printf_filtered ("Instruction Pointer: %s:",
382 local_hex_string_custom (fiseg, "02"));
383 printf_filtered ("%s\n", local_hex_string_custom (fioff, "08"));
384 printf_filtered ("Operand Pointer: %s:",
385 local_hex_string_custom (foseg, "02"));
386 printf_filtered ("%s\n", local_hex_string_custom (fooff, "08"));
387 printf_filtered ("Opcode: %s\n",
388 local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
389 }
390
391 \f
392 /* FIXME: The functions on this page are used to provide `long double'
393 support for Linux. However, the approach does not seem to be the
394 right one, and we are planning to solve this in a way that should
395 work for all i386 targets. These functions will disappear in the
396 near future, so please don't use them. */
397 #ifdef LD_I387
398 int
399 i387_extract_floating (PTR addr, int len, DOUBLEST *dretptr)
400 {
401 if (len == TARGET_LONG_DOUBLE_BIT / 8)
402 {
403 if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
404 {
405 DOUBLEST retval;
406
407 memcpy (dretptr, addr, sizeof (retval));
408 }
409 else
410 floatformat_to_doublest (TARGET_LONG_DOUBLE_FORMAT, addr, dretptr);
411
412 return 1;
413 }
414 else
415 return 0;
416 }
417
418 int
419 i387_store_floating (PTR addr, int len, DOUBLEST val)
420 {
421 if (len == TARGET_LONG_DOUBLE_BIT / 8)
422 {
423 /* This `if' may be totally stupid. I just put it in here to be
424 absolutely sure I'm preserving the semantics of the code I'm
425 frobbing, while I try to maintain portability boundaries; I
426 don't actually know exactly what it's doing. -JimB, May 1999 */
427 if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
428 memcpy (addr, &val, sizeof (val));
429 else
430 floatformat_from_doublest (TARGET_LONG_DOUBLE_FORMAT, &val, addr);
431
432 return 1;
433 }
434 else
435 return 0;
436 }
437 #endif /* LD_I387 */