2a6f77ce42d4429fd03a6084f9685490484ab6ea
[platform/upstream/binutils.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 #include "i386-tdep.h"
34
35 /* FIXME: Eliminate the next two functions when we have the time to
36    change all the callers.  */
37
38 void i387_to_double (char *from, char *to);
39 void double_to_i387 (char *from, char *to);
40
41 void
42 i387_to_double (char *from, char *to)
43 {
44   floatformat_to_double (&floatformat_i387_ext, from, (double *) to);
45 }
46
47 void
48 double_to_i387 (char *from, char *to)
49 {
50   floatformat_from_double (&floatformat_i387_ext, (double *) from, to);
51 }
52
53 \f
54 /* FIXME: The functions on this page are used by the old `info float'
55    implementations that a few of the i386 targets provide.  These
56    functions should be removed if all of these have been converted to
57    use the generic implementation based on the new register file
58    layout.  */
59
60 static void print_387_control_bits (unsigned int control);
61 static void print_387_status_bits (unsigned int status);
62
63 static void
64 print_387_control_bits (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 (unsigned int control)
121 {
122   printf_filtered ("control %s:", local_hex_string(control & 0xffff));
123   print_387_control_bits (control);
124   puts_unfiltered ("\n");
125 }
126
127 static void
128 print_387_status_bits (unsigned int status)
129 {
130   printf_unfiltered (" flags %d%d%d%d; ",
131                      (status & 0x4000) != 0,
132                      (status & 0x0400) != 0,
133                      (status & 0x0200) != 0,
134                      (status & 0x0100) != 0);
135   printf_unfiltered ("top %d; ", (status >> 11) & 7);
136   if (status & 0xff) 
137     {
138       puts_unfiltered ("excep");
139       if (status & 0x0001) puts_unfiltered (" INVAL");
140       if (status & 0x0002) puts_unfiltered (" DENOR");
141       if (status & 0x0004) puts_unfiltered (" DIVZ");
142       if (status & 0x0008) puts_unfiltered (" OVERF");
143       if (status & 0x0010) puts_unfiltered (" UNDER");
144       if (status & 0x0020) puts_unfiltered (" LOS");
145       if (status & 0x0040) puts_unfiltered (" STACK");
146     }
147 }
148
149 void
150 print_387_status_word (unsigned int status)
151 {
152   printf_filtered ("status %s:", local_hex_string (status & 0xffff));
153   print_387_status_bits (status);
154   puts_unfiltered ("\n");
155 }
156
157 \f
158 /* Implement the `info float' layout based on the register definitions
159    in `tm-i386.h'.  */
160
161 /* Print the floating point number specified by RAW.  */
162 static void
163 print_i387_value (char *raw)
164 {
165   DOUBLEST value;
166
167   /* Using extract_typed_floating here might affect the representation
168      of certain numbers such as NaNs, even if GDB is running natively.
169      This is fine since our caller already detects such special
170      numbers and we print the hexadecimal representation anyway.  */
171   value = extract_typed_floating (raw, builtin_type_i387_ext);
172
173   /* We try to print 19 digits.  The last digit may or may not contain
174      garbage, but we'd better print one too many.  We need enough room
175      to print the value, 1 position for the sign, 1 for the decimal
176      point, 19 for the digits and 6 for the exponent adds up to 27.  */
177 #ifdef PRINTF_HAS_LONG_DOUBLE
178   printf_filtered (" %-+27.19Lg", (long double) value);
179 #else
180   printf_filtered (" %-+27.19g", (double) value);
181 #endif
182 }
183
184 /* Print the classification for the register contents RAW.  */
185 static void
186 print_i387_ext (unsigned char *raw)
187 {
188   int sign;
189   int integer;
190   unsigned int exponent;
191   unsigned long fraction[2];
192
193   sign = raw[9] & 0x80;
194   integer = raw[7] & 0x80;
195   exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
196   fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
197   fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
198                  | (raw[5] << 8) | raw[4]);
199
200   if (exponent == 0x7fff && integer)
201     {
202       if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
203         /* Infinity.  */
204         printf_filtered (" %cInf", (sign ? '-' : '+'));
205       else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
206         /* Real Indefinite (QNaN).  */
207         puts_unfiltered (" Real Indefinite (QNaN)");
208       else if (fraction[1] & 0x40000000)
209         /* QNaN.  */
210         puts_filtered (" QNaN");
211       else
212         /* SNaN.  */
213         puts_filtered (" SNaN");
214     }
215   else if (exponent < 0x7fff && exponent > 0x0000 && integer)
216     /* Normal.  */
217     print_i387_value (raw);
218   else if (exponent == 0x0000)
219     {
220       /* Denormal or zero.  */
221       print_i387_value (raw);
222       
223       if (integer)
224         /* Pseudo-denormal.  */
225         puts_filtered (" Pseudo-denormal");
226       else if (fraction[0] || fraction[1])
227         /* Denormal.  */
228         puts_filtered (" Denormal");
229     }
230   else
231     /* Unsupported.  */
232     puts_filtered (" Unsupported");
233 }
234
235 /* Print the status word STATUS.  */
236 static void
237 print_i387_status_word (unsigned int status)
238 {
239   printf_filtered ("Status Word:         %s",
240                    local_hex_string_custom (status, "04"));
241   puts_filtered ("  ");
242   printf_filtered (" %s", (status & 0x0001) ? "IE" : "  ");
243   printf_filtered (" %s", (status & 0x0002) ? "DE" : "  ");
244   printf_filtered (" %s", (status & 0x0004) ? "ZE" : "  ");
245   printf_filtered (" %s", (status & 0x0008) ? "OE" : "  ");
246   printf_filtered (" %s", (status & 0x0010) ? "UE" : "  ");
247   printf_filtered (" %s", (status & 0x0020) ? "PE" : "  ");
248   puts_filtered ("  ");
249   printf_filtered (" %s", (status & 0x0080) ? "ES" : "  ");
250   puts_filtered ("  ");
251   printf_filtered (" %s", (status & 0x0040) ? "SF" : "  ");
252   puts_filtered ("  ");
253   printf_filtered (" %s", (status & 0x0100) ? "C0" : "  ");
254   printf_filtered (" %s", (status & 0x0200) ? "C1" : "  ");
255   printf_filtered (" %s", (status & 0x0400) ? "C2" : "  ");
256   printf_filtered (" %s", (status & 0x4000) ? "C3" : "  ");
257
258   puts_filtered ("\n");
259
260   printf_filtered ("                       TOP: %d\n", ((status >> 11) & 7));
261 }
262
263 /* Print the control word CONTROL.  */
264 static void
265 print_i387_control_word (unsigned int control)
266 {
267   printf_filtered ("Control Word:        %s",
268                    local_hex_string_custom (control, "04"));
269   puts_filtered ("  ");
270   printf_filtered (" %s", (control & 0x0001) ? "IM" : "  ");
271   printf_filtered (" %s", (control & 0x0002) ? "DM" : "  ");
272   printf_filtered (" %s", (control & 0x0004) ? "ZM" : "  ");
273   printf_filtered (" %s", (control & 0x0008) ? "OM" : "  ");
274   printf_filtered (" %s", (control & 0x0010) ? "UM" : "  ");
275   printf_filtered (" %s", (control & 0x0020) ? "PM" : "  ");
276
277   puts_filtered ("\n");
278
279   puts_filtered ("                       PC: ");
280   switch ((control >> 8) & 3)
281     {
282     case 0:
283       puts_filtered ("Single Precision (24-bits)\n");
284       break;
285     case 1:
286       puts_filtered ("Reserved\n");
287       break;
288     case 2:
289       puts_filtered ("Double Precision (53-bits)\n");
290       break;
291     case 3:
292       puts_filtered ("Extended Precision (64-bits)\n");
293       break;
294     }
295       
296   puts_filtered ("                       RC: ");
297   switch ((control >> 10) & 3)
298     {
299     case 0:
300       puts_filtered ("Round to nearest\n");
301       break;
302     case 1:
303       puts_filtered ("Round down\n");
304       break;
305     case 2:
306       puts_filtered ("Round up\n");
307       break;
308     case 3:
309       puts_filtered ("Round toward zero\n");
310       break;
311     }
312 }
313
314 /* Print out the i387 floating poin state.  */
315 void
316 i387_float_info (void)
317 {
318   unsigned int fctrl;
319   unsigned int fstat;
320   unsigned int ftag;
321   unsigned int fiseg;
322   unsigned int fioff;
323   unsigned int foseg;
324   unsigned int fooff;
325   unsigned int fop;
326   int fpreg;
327   int top;
328
329   fctrl = read_register (FCTRL_REGNUM);
330   fstat = read_register (FSTAT_REGNUM);
331   ftag  = read_register (FTAG_REGNUM);
332   fiseg = read_register (FCS_REGNUM);
333   fioff = read_register (FCOFF_REGNUM);
334   foseg = read_register (FDS_REGNUM);
335   fooff = read_register (FDOFF_REGNUM);
336   fop   = read_register (FOP_REGNUM);
337   
338   top = ((fstat >> 11) & 7);
339
340   for (fpreg = 7; fpreg >= 0; fpreg--)
341     {
342       unsigned char raw[FPU_REG_RAW_SIZE];
343       int tag = (ftag >> (fpreg * 2)) & 3;
344       int i;
345
346       printf_filtered ("%sR%d: ", fpreg == top ? "=>" : "  ", fpreg);
347
348       switch (tag)
349         {
350         case 0:
351           puts_filtered ("Valid   ");
352           break;
353         case 1:
354           puts_filtered ("Zero    ");
355           break;
356         case 2:
357           puts_filtered ("Special ");
358           break;
359         case 3:
360           puts_filtered ("Empty   ");
361           break;
362         }
363
364       read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
365
366       puts_filtered ("0x");
367       for (i = 9; i >= 0; i--)
368         printf_filtered ("%02x", raw[i]);
369
370       if (tag != 3)
371         print_i387_ext (raw);
372
373       puts_filtered ("\n");
374     }
375
376   puts_filtered ("\n");
377
378   print_i387_status_word (fstat);
379   print_i387_control_word (fctrl);
380   printf_filtered ("Tag Word:            %s\n",
381                    local_hex_string_custom (ftag, "04"));
382   printf_filtered ("Instruction Pointer: %s:",
383                    local_hex_string_custom (fiseg, "02"));
384   printf_filtered ("%s\n", local_hex_string_custom (fioff, "08"));
385   printf_filtered ("Operand Pointer:     %s:",
386                    local_hex_string_custom (foseg, "02"));
387   printf_filtered ("%s\n", local_hex_string_custom (fooff, "08"));
388   printf_filtered ("Opcode:              %s\n",
389                    local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
390 }