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