4f180fa8fa7bcff809d52eb7e9b6e0636e912939
[platform/upstream/binutils.git] / gdb / i387-tdep.c
1 /* Intel 387 floating point stuff.
2    Copyright (C) 1988, 89, 91, 98, 99, 2000 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 (char *from, char *to);
34 void double_to_i387 (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 (unsigned int control);
60 static void print_387_status_bits (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   /* Avoid call to floatformat_to_doublest if possible to preserve as
171      much information as possible.  */
172
173 #ifdef HAVE_LONG_DOUBLE
174   if (sizeof (value) == sizeof (long double)
175       && HOST_LONG_DOUBLE_FORMAT == &floatformat_i387_ext)
176     {
177       /* Copy straight over, but take care of the padding.  */
178       memcpy (&value, raw, FPU_REG_RAW_SIZE);
179       memset ((char *) &value + FPU_REG_RAW_SIZE, 0,
180               sizeof (value) - FPU_REG_RAW_SIZE);
181     }
182   else
183 #endif
184     floatformat_to_doublest (&floatformat_i387_ext, raw, &value);
185
186   /* We try to print 19 digits.  The last digit may or may not contain
187      garbage, but we'd better print one too many.  We need enough room
188      to print the value, 1 position for the sign, 1 for the decimal
189      point, 19 for the digits and 6 for the exponent adds up to 27.  */
190 #ifdef PRINTF_HAS_LONG_DOUBLE
191   printf_filtered (" %-+27.19Lg", (long double) value);
192 #else
193   printf_filtered (" %-+27.19g", (double) value);
194 #endif
195 }
196
197 /* Print the classification for the register contents RAW.  */
198 static void
199 print_i387_ext (unsigned char *raw)
200 {
201   int sign;
202   int integer;
203   unsigned int exponent;
204   unsigned long fraction[2];
205
206   sign = raw[9] & 0x80;
207   integer = raw[7] & 0x80;
208   exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
209   fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
210   fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
211                  | (raw[5] << 8) | raw[4]);
212
213   if (exponent == 0x7fff && integer)
214     {
215       if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
216         /* Infinity.  */
217         printf_filtered (" %cInf", (sign ? '-' : '+'));
218       else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
219         /* Real Indefinite (QNaN).  */
220         puts_unfiltered (" Real Indefinite (QNaN)");
221       else if (fraction[1] & 0x40000000)
222         /* QNaN.  */
223         puts_filtered (" QNaN");
224       else
225         /* SNaN.  */
226         puts_filtered (" SNaN");
227     }
228   else if (exponent < 0x7fff && exponent > 0x0000 && integer)
229     /* Normal.  */
230     print_i387_value (raw);
231   else if (exponent == 0x0000)
232     {
233       /* Denormal or zero.  */
234       print_i387_value (raw);
235       
236       if (integer)
237         /* Pseudo-denormal.  */
238         puts_filtered (" Pseudo-denormal");
239       else if (fraction[0] || fraction[1])
240         /* Denormal.  */
241         puts_filtered (" Denormal");
242     }
243   else
244     /* Unsupported.  */
245     puts_filtered (" Unsupported");
246 }
247
248 /* Print the status word STATUS.  */
249 static void
250 print_i387_status_word (unsigned int status)
251 {
252   printf_filtered ("Status Word:         %s",
253                    local_hex_string_custom (status, "04"));
254   puts_filtered ("  ");
255   printf_filtered (" %s", (status & 0x0001) ? "IE" : "  ");
256   printf_filtered (" %s", (status & 0x0002) ? "DE" : "  ");
257   printf_filtered (" %s", (status & 0x0004) ? "ZE" : "  ");
258   printf_filtered (" %s", (status & 0x0008) ? "OE" : "  ");
259   printf_filtered (" %s", (status & 0x0010) ? "UE" : "  ");
260   printf_filtered (" %s", (status & 0x0020) ? "PE" : "  ");
261   puts_filtered ("  ");
262   printf_filtered (" %s", (status & 0x0080) ? "ES" : "  ");
263   puts_filtered ("  ");
264   printf_filtered (" %s", (status & 0x0080) ? "SF" : "  ");
265   puts_filtered ("  ");
266   printf_filtered (" %s", (status & 0x0100) ? "C0" : "  ");
267   printf_filtered (" %s", (status & 0x0200) ? "C1" : "  ");
268   printf_filtered (" %s", (status & 0x0400) ? "C2" : "  ");
269   printf_filtered (" %s", (status & 0x4000) ? "C3" : "  ");
270
271   puts_filtered ("\n");
272
273   printf_filtered ("                       TOP: %d\n", ((status >> 11) & 7));
274 }
275
276 /* Print the control word CONTROL.  */
277 static void
278 print_i387_control_word (unsigned int control)
279 {
280   printf_filtered ("Control Word:        %s",
281                    local_hex_string_custom (control, "04"));
282   puts_filtered ("  ");
283   printf_filtered (" %s", (control & 0x0001) ? "IM" : "  ");
284   printf_filtered (" %s", (control & 0x0002) ? "DM" : "  ");
285   printf_filtered (" %s", (control & 0x0004) ? "ZM" : "  ");
286   printf_filtered (" %s", (control & 0x0008) ? "OM" : "  ");
287   printf_filtered (" %s", (control & 0x0010) ? "UM" : "  ");
288   printf_filtered (" %s", (control & 0x0020) ? "PM" : "  ");
289
290   puts_filtered ("\n");
291
292   puts_filtered ("                       PC: ");
293   switch ((control >> 8) & 3)
294     {
295     case 0:
296       puts_filtered ("Single Precision (24-bits)\n");
297       break;
298     case 1:
299       puts_filtered ("Reserved\n");
300       break;
301     case 2:
302       puts_filtered ("Double Precision (53-bits)\n");
303       break;
304     case 3:
305       puts_filtered ("Extended Precision (64-bits)\n");
306       break;
307     }
308       
309   puts_filtered ("                       RC: ");
310   switch ((control >> 10) & 3)
311     {
312     case 0:
313       puts_filtered ("Round to nearest\n");
314       break;
315     case 1:
316       puts_filtered ("Round down\n");
317       break;
318     case 2:
319       puts_filtered ("Round up\n");
320       break;
321     case 3:
322       puts_filtered ("Round toward zero\n");
323       break;
324     }
325 }
326
327 /* Print out the i387 floating poin state.  */
328 void
329 i387_float_info (void)
330 {
331   unsigned int fctrl;
332   unsigned int fstat;
333   unsigned int ftag;
334   unsigned int fiseg;
335   unsigned int fioff;
336   unsigned int foseg;
337   unsigned int fooff;
338   unsigned int fop;
339   int fpreg;
340   int top;
341
342   fctrl = read_register (FCTRL_REGNUM);
343   fstat = read_register (FSTAT_REGNUM);
344   ftag  = read_register (FTAG_REGNUM);
345   fiseg = read_register (FCS_REGNUM);
346   fioff = read_register (FCOFF_REGNUM);
347   foseg = read_register (FDS_REGNUM);
348   fooff = read_register (FDOFF_REGNUM);
349   fop   = read_register (FOP_REGNUM);
350   
351   top = ((fstat >> 11) & 7);
352
353   for (fpreg = 7; fpreg >= 0; fpreg--)
354     {
355       unsigned char raw[FPU_REG_RAW_SIZE];
356       int tag = (ftag >> (fpreg * 2)) & 3;
357       int i;
358
359       printf_filtered ("%sR%d: ", fpreg == top ? "=>" : "  ", fpreg);
360
361       switch (tag)
362         {
363         case 0:
364           puts_filtered ("Valid   ");
365           break;
366         case 1:
367           puts_filtered ("Zero    ");
368           break;
369         case 2:
370           puts_filtered ("Special ");
371           break;
372         case 3:
373           puts_filtered ("Empty   ");
374           break;
375         }
376
377       read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
378
379       puts_filtered ("0x");
380       for (i = 9; i >= 0; i--)
381         printf_filtered ("%02x", raw[i]);
382
383       if (tag != 3)
384         print_i387_ext (raw);
385
386       puts_filtered ("\n");
387     }
388
389   puts_filtered ("\n");
390
391   print_i387_status_word (fstat);
392   print_i387_control_word (fctrl);
393   printf_filtered ("Tag Word:            %s\n",
394                    local_hex_string_custom (ftag, "04"));
395   printf_filtered ("Instruction Pointer: %s:",
396                    local_hex_string_custom (fiseg, "02"));
397   printf_filtered ("%s\n", local_hex_string_custom (fioff, "08"));
398   printf_filtered ("Operand Pointer:     %s:",
399                    local_hex_string_custom (foseg, "02"));
400   printf_filtered ("%s\n", local_hex_string_custom (fooff, "08"));
401   printf_filtered ("Opcode:              %s\n",
402                    local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
403 }