OSDN Git Service

* libc/posix/execvp.c (execvp): Check path for
[pf3gnuchains/pf3gnuchains4x.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 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   /* Avoid call to floatformat_to_doublest if possible to preserve as
171      much information as possible.  */
172
173 #ifdef HAVE_LONG_DOUBLE
174   if (sizeof (value) == sizeof (long double)
175       && HOST_LONG_DOUBLE_FORMAT == &floatformat_i387_ext)
176     {
177       /* Copy straight over, but take care of the padding.  */
178       memcpy (&value, raw, FPU_REG_RAW_SIZE);
179       memset (&value + FPU_REG_RAW_SIZE, 0, sizeof (value) - FPU_REG_RAW_SIZE);
180     }
181   else
182 #endif
183     floatformat_to_doublest (&floatformat_i387_ext, raw, &value);
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 & 0x0080) ? "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 }