* i387-tdep.c (print_i387_value): Use extract_typed_floating to
[external/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 #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 }