OSDN Git Service

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