This commit was generated by cvs2svn to track changes on a CVS vendor
[platform/upstream/binutils.git] / gdb / i387-tdep.c
1 /* Intel 387 floating point stuff.
2    Copyright (C) 1988, 1989, 1991, 1998, 1999 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 PARAMS ((char *from, char *to));
34 void double_to_i387 PARAMS ((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 PARAMS ((unsigned int control));
60 static void print_387_status_bits PARAMS ((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   floatformat_to_doublest (&floatformat_i387_ext, raw, &value);
171
172   /* We try to print 19 digits.  The last digit may or may not contain
173      garbage, but we'd better print one too many.  We need enough room
174      to print the value, 1 position for the sign, 1 for the decimal
175      point, 19 for the digits and 6 for the exponent adds up to 27.  */
176 #ifdef PRINTF_HAS_LONG_DOUBLE
177   printf_filtered (" %-+27.19Lg", (long double) value);
178 #else
179   printf_filtered (" %-+27.19g", (double) value);
180 #endif
181 }
182
183 /* Print the classification for the register contents RAW.  */
184 static void
185 print_i387_ext (unsigned char *raw)
186 {
187   int sign;
188   int integer;
189   unsigned int exponent;
190   unsigned long fraction[2];
191
192   sign = raw[9] & 0x80;
193   integer = raw[7] & 0x80;
194   exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
195   fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
196   fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
197                  | (raw[5] << 8) | raw[4]);
198
199   if (exponent == 0x7fff && integer)
200     {
201       if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
202         /* Infinity.  */
203         printf_filtered (" %cInf", (sign ? '-' : '+'));
204       else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
205         /* Real Indefinite (QNaN).  */
206         puts_unfiltered (" Real Indefinite (QNaN)");
207       else if (fraction[1] & 0x40000000)
208         /* QNaN.  */
209         puts_filtered (" QNaN");
210       else
211         /* SNaN.  */
212         puts_filtered (" SNaN");
213     }
214   else if (exponent < 0x7fff && exponent > 0x0000 && integer)
215     /* Normal.  */
216     print_i387_value (raw);
217   else if (exponent == 0x0000)
218     {
219       /* Denormal or zero.  */
220       print_i387_value (raw);
221       
222       if (integer)
223         /* Pseudo-denormal.  */
224         puts_filtered (" Pseudo-denormal");
225       else if (fraction[0] || fraction[1])
226         /* Denormal.  */
227         puts_filtered (" Denormal");
228     }
229   else
230     /* Unsupported.  */
231     puts_filtered (" Unsupported");
232 }
233
234 /* Print the status word STATUS.  */
235 static void
236 print_i387_status_word (unsigned int status)
237 {
238   printf_filtered ("Status Word:         %s",
239                    local_hex_string_custom (status, "04"));
240   puts_filtered ("  ");
241   printf_filtered (" %s", (status & 0x0001) ? "IE" : "  ");
242   printf_filtered (" %s", (status & 0x0002) ? "DE" : "  ");
243   printf_filtered (" %s", (status & 0x0004) ? "ZE" : "  ");
244   printf_filtered (" %s", (status & 0x0008) ? "OE" : "  ");
245   printf_filtered (" %s", (status & 0x0010) ? "UE" : "  ");
246   printf_filtered (" %s", (status & 0x0020) ? "PE" : "  ");
247   puts_filtered ("  ");
248   printf_filtered (" %s", (status & 0x0080) ? "ES" : "  ");
249   puts_filtered ("  ");
250   printf_filtered (" %s", (status & 0x0080) ? "SF" : "  ");
251   puts_filtered ("  ");
252   printf_filtered (" %s", (status & 0x0100) ? "C0" : "  ");
253   printf_filtered (" %s", (status & 0x0200) ? "C1" : "  ");
254   printf_filtered (" %s", (status & 0x0400) ? "C2" : "  ");
255   printf_filtered (" %s", (status & 0x4000) ? "C3" : "  ");
256
257   puts_filtered ("\n");
258
259   printf_filtered ("                       TOP: %d\n", ((status >> 11) & 7));
260 }
261
262 /* Print the control word CONTROL.  */
263 static void
264 print_i387_control_word (unsigned int control)
265 {
266   printf_filtered ("Control Word:        %s",
267                    local_hex_string_custom (control, "04"));
268   puts_filtered ("  ");
269   printf_filtered (" %s", (control & 0x0001) ? "IM" : "  ");
270   printf_filtered (" %s", (control & 0x0002) ? "DM" : "  ");
271   printf_filtered (" %s", (control & 0x0004) ? "ZM" : "  ");
272   printf_filtered (" %s", (control & 0x0008) ? "OM" : "  ");
273   printf_filtered (" %s", (control & 0x0010) ? "UM" : "  ");
274   printf_filtered (" %s", (control & 0x0020) ? "PM" : "  ");
275
276   puts_filtered ("\n");
277
278   puts_filtered ("                       PC: ");
279   switch ((control >> 8) & 3)
280     {
281     case 0:
282       puts_filtered ("Single Precision (24-bits)\n");
283       break;
284     case 1:
285       puts_filtered ("Reserved\n");
286       break;
287     case 2:
288       puts_filtered ("Double Precision (53-bits)\n");
289       break;
290     case 3:
291       puts_filtered ("Extended Precision (64-bits)\n");
292       break;
293     }
294       
295   puts_filtered ("                       RC: ");
296   switch ((control >> 10) & 3)
297     {
298     case 0:
299       puts_filtered ("Round to nearest\n");
300       break;
301     case 1:
302       puts_filtered ("Round down\n");
303       break;
304     case 2:
305       puts_filtered ("Round up\n");
306       break;
307     case 3:
308       puts_filtered ("Round toward zero\n");
309       break;
310     }
311 }
312
313 /* Print out the i387 floating poin state.  */
314 void
315 i387_float_info (void)
316 {
317   unsigned int fctrl;
318   unsigned int fstat;
319   unsigned int ftag;
320   unsigned int fiseg;
321   unsigned int fioff;
322   unsigned int foseg;
323   unsigned int fooff;
324   unsigned int fop;
325   int fpreg;
326   int top;
327
328   fctrl = read_register (FCTRL_REGNUM);
329   fstat = read_register (FSTAT_REGNUM);
330   ftag  = read_register (FTAG_REGNUM);
331   fiseg = read_register (FCS_REGNUM);
332   fioff = read_register (FCOFF_REGNUM);
333   foseg = read_register (FDS_REGNUM);
334   fooff = read_register (FDOFF_REGNUM);
335   fop   = read_register (FOP_REGNUM);
336   
337   top = ((fstat >> 11) & 7);
338
339   for (fpreg = 7; fpreg >= 0; fpreg--)
340     {
341       unsigned char raw[FPU_REG_RAW_SIZE];
342       int tag = (ftag >> (fpreg * 2)) & 3;
343       int i;
344
345       printf_filtered ("%sR%d: ", fpreg == top ? "=>" : "  ", fpreg);
346
347       switch (tag)
348         {
349         case 0:
350           puts_filtered ("Valid   ");
351           break;
352         case 1:
353           puts_filtered ("Zero    ");
354           break;
355         case 2:
356           puts_filtered ("Special ");
357           break;
358         case 3:
359           puts_filtered ("Empty   ");
360           break;
361         }
362
363       read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
364
365       puts_filtered ("0x");
366       for (i = 9; i >= 0; i--)
367         printf_filtered ("%02x", raw[i]);
368
369       if (tag != 3)
370         print_i387_ext (raw);
371
372       puts_filtered ("\n");
373     }
374
375   puts_filtered ("\n");
376
377   print_i387_status_word (fstat);
378   print_i387_control_word (fctrl);
379   printf_filtered ("Tag Word:            %s\n",
380                    local_hex_string_custom (ftag, "04"));
381   printf_filtered ("Instruction Pointer: %s:",
382                    local_hex_string_custom (fiseg, "02"));
383   printf_filtered ("%s\n", local_hex_string_custom (fioff, "08"));
384   printf_filtered ("Operand Pointer:     %s:",
385                    local_hex_string_custom (foseg, "02"));
386   printf_filtered ("%s\n", local_hex_string_custom (fooff, "08"));
387   printf_filtered ("Opcode:              %s\n",
388                    local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
389 }
390
391 \f
392 /* FIXME: The functions on this page are used to provide `long double'
393    support for Linux.  However, the approach does not seem to be the
394    right one, and we are planning to solve this in a way that should
395    work for all i386 targets.  These functions will disappear in the
396    near future, so please don't use them.  */
397 #ifdef LD_I387
398 int
399 i387_extract_floating (PTR addr, int len, DOUBLEST *dretptr)
400 {
401   if (len == TARGET_LONG_DOUBLE_BIT / 8)
402     {
403       if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
404         {
405           DOUBLEST retval;
406
407           memcpy (dretptr, addr, sizeof (retval));
408         }
409       else
410         floatformat_to_doublest (TARGET_LONG_DOUBLE_FORMAT, addr, dretptr);
411
412       return 1;
413     }
414   else
415     return 0;
416 }
417
418 int
419 i387_store_floating (PTR addr, int len, DOUBLEST val)
420 {
421   if (len == TARGET_LONG_DOUBLE_BIT / 8)
422     {
423       /* This `if' may be totally stupid.  I just put it in here to be
424          absolutely sure I'm preserving the semantics of the code I'm
425          frobbing, while I try to maintain portability boundaries; I
426          don't actually know exactly what it's doing.  -JimB, May 1999 */
427       if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
428         memcpy (addr, &val, sizeof (val));
429       else
430         floatformat_from_doublest (TARGET_LONG_DOUBLE_FORMAT, &val, addr);
431
432       return 1;
433     }
434   else
435     return 0;
436 }
437 #endif /* LD_I387 */