* Makefile.in (osabi.o, i387-tdep.o, i386-linux-nat.o, lin-lwp.o,
[external/binutils.git] / gdb / i387-tdep.c
1 /* Intel 387 floating point stuff.
2    Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000,
3    2001, 2002 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 "gdb_string.h"
32 #include "doublest.h"
33
34 #include "i386-tdep.h"
35
36 /* FIXME: Eliminate the next two functions when we have the time to
37    change all the callers.  */
38
39 void i387_to_double (char *from, char *to);
40 void double_to_i387 (char *from, char *to);
41
42 void
43 i387_to_double (char *from, char *to)
44 {
45   floatformat_to_double (&floatformat_i387_ext, from, (double *) to);
46 }
47
48 void
49 double_to_i387 (char *from, char *to)
50 {
51   floatformat_from_double (&floatformat_i387_ext, (double *) from, to);
52 }
53
54 \f
55 /* FIXME: The functions on this page are used by the old `info float'
56    implementations that a few of the i386 targets provide.  These
57    functions should be removed if all of these have been converted to
58    use the generic implementation based on the new register file
59    layout.  */
60
61 static void print_387_control_bits (unsigned int control);
62 static void print_387_status_bits (unsigned int status);
63
64 static void
65 print_387_control_bits (unsigned int control)
66 {
67   switch ((control >> 8) & 3)
68     {
69     case 0:
70       puts_unfiltered (" 24 bit; ");
71       break;
72     case 1:
73       puts_unfiltered (" (bad); ");
74       break;
75     case 2:
76       puts_unfiltered (" 53 bit; ");
77       break;
78     case 3:
79       puts_unfiltered (" 64 bit; ");
80       break;
81     }
82   switch ((control >> 10) & 3)
83     {
84     case 0:
85       puts_unfiltered ("NEAR; ");
86       break;
87     case 1:
88       puts_unfiltered ("DOWN; ");
89       break;
90     case 2:
91       puts_unfiltered ("UP; ");
92       break;
93     case 3:
94       puts_unfiltered ("CHOP; ");
95       break;
96     }
97   if (control & 0x3f)
98     {
99       puts_unfiltered ("mask");
100       if (control & 0x0001)
101         puts_unfiltered (" INVAL");
102       if (control & 0x0002)
103         puts_unfiltered (" DENOR");
104       if (control & 0x0004)
105         puts_unfiltered (" DIVZ");
106       if (control & 0x0008)
107         puts_unfiltered (" OVERF");
108       if (control & 0x0010)
109         puts_unfiltered (" UNDER");
110       if (control & 0x0020)
111         puts_unfiltered (" LOS");
112       puts_unfiltered (";");
113     }
114
115   if (control & 0xe080)
116     warning ("\nreserved bits on: %s",
117              local_hex_string (control & 0xe080));
118 }
119
120 void
121 print_387_control_word (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 (unsigned int status)
130 {
131   printf_unfiltered (" flags %d%d%d%d; ",
132                      (status & 0x4000) != 0,
133                      (status & 0x0400) != 0,
134                      (status & 0x0200) != 0,
135                      (status & 0x0100) != 0);
136   printf_unfiltered ("top %d; ", (status >> 11) & 7);
137   if (status & 0xff) 
138     {
139       puts_unfiltered ("excep");
140       if (status & 0x0001) puts_unfiltered (" INVAL");
141       if (status & 0x0002) puts_unfiltered (" DENOR");
142       if (status & 0x0004) puts_unfiltered (" DIVZ");
143       if (status & 0x0008) puts_unfiltered (" OVERF");
144       if (status & 0x0010) puts_unfiltered (" UNDER");
145       if (status & 0x0020) puts_unfiltered (" LOS");
146       if (status & 0x0040) puts_unfiltered (" STACK");
147     }
148 }
149
150 void
151 print_387_status_word (unsigned int status)
152 {
153   printf_filtered ("status %s:", local_hex_string (status & 0xffff));
154   print_387_status_bits (status);
155   puts_unfiltered ("\n");
156 }
157
158 \f
159 /* Implement the `info float' layout based on the register definitions
160    in `tm-i386.h'.  */
161
162 /* Print the floating point number specified by RAW.  */
163 static void
164 print_i387_value (char *raw, struct ui_file *file)
165 {
166   DOUBLEST value;
167
168   /* Using extract_typed_floating here might affect the representation
169      of certain numbers such as NaNs, even if GDB is running natively.
170      This is fine since our caller already detects such special
171      numbers and we print the hexadecimal representation anyway.  */
172   value = extract_typed_floating (raw, builtin_type_i387_ext);
173
174   /* We try to print 19 digits.  The last digit may or may not contain
175      garbage, but we'd better print one too many.  We need enough room
176      to print the value, 1 position for the sign, 1 for the decimal
177      point, 19 for the digits and 6 for the exponent adds up to 27.  */
178 #ifdef PRINTF_HAS_LONG_DOUBLE
179   fprintf_filtered (file, " %-+27.19Lg", (long double) value);
180 #else
181   fprintf_filtered (file, " %-+27.19g", (double) value);
182 #endif
183 }
184
185 /* Print the classification for the register contents RAW.  */
186 static void
187 print_i387_ext (unsigned char *raw, struct ui_file *file)
188 {
189   int sign;
190   int integer;
191   unsigned int exponent;
192   unsigned long fraction[2];
193
194   sign = raw[9] & 0x80;
195   integer = raw[7] & 0x80;
196   exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
197   fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
198   fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
199                  | (raw[5] << 8) | raw[4]);
200
201   if (exponent == 0x7fff && integer)
202     {
203       if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
204         /* Infinity.  */
205         fprintf_filtered (file, " %cInf", (sign ? '-' : '+'));
206       else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
207         /* Real Indefinite (QNaN).  */
208         fputs_unfiltered (" Real Indefinite (QNaN)", file);
209       else if (fraction[1] & 0x40000000)
210         /* QNaN.  */
211         fputs_filtered (" QNaN", file);
212       else
213         /* SNaN.  */
214         fputs_filtered (" SNaN", file);
215     }
216   else if (exponent < 0x7fff && exponent > 0x0000 && integer)
217     /* Normal.  */
218     print_i387_value (raw, file);
219   else if (exponent == 0x0000)
220     {
221       /* Denormal or zero.  */
222       print_i387_value (raw, file);
223       
224       if (integer)
225         /* Pseudo-denormal.  */
226         fputs_filtered (" Pseudo-denormal", file);
227       else if (fraction[0] || fraction[1])
228         /* Denormal.  */
229         fputs_filtered (" Denormal", file);
230     }
231   else
232     /* Unsupported.  */
233     fputs_filtered (" Unsupported", file);
234 }
235
236 /* Print the status word STATUS.  */
237 static void
238 print_i387_status_word (unsigned int status, struct ui_file *file)
239 {
240   fprintf_filtered (file, "Status Word:         %s",
241                    local_hex_string_custom (status, "04"));
242   fputs_filtered ("  ", file);
243   fprintf_filtered (file, " %s", (status & 0x0001) ? "IE" : "  ");
244   fprintf_filtered (file, " %s", (status & 0x0002) ? "DE" : "  ");
245   fprintf_filtered (file, " %s", (status & 0x0004) ? "ZE" : "  ");
246   fprintf_filtered (file, " %s", (status & 0x0008) ? "OE" : "  ");
247   fprintf_filtered (file, " %s", (status & 0x0010) ? "UE" : "  ");
248   fprintf_filtered (file, " %s", (status & 0x0020) ? "PE" : "  ");
249   fputs_filtered ("  ", file);
250   fprintf_filtered (file, " %s", (status & 0x0080) ? "ES" : "  ");
251   fputs_filtered ("  ", file);
252   fprintf_filtered (file, " %s", (status & 0x0040) ? "SF" : "  ");
253   fputs_filtered ("  ", file);
254   fprintf_filtered (file, " %s", (status & 0x0100) ? "C0" : "  ");
255   fprintf_filtered (file, " %s", (status & 0x0200) ? "C1" : "  ");
256   fprintf_filtered (file, " %s", (status & 0x0400) ? "C2" : "  ");
257   fprintf_filtered (file, " %s", (status & 0x4000) ? "C3" : "  ");
258
259   fputs_filtered ("\n", file);
260
261   fprintf_filtered (file,
262                     "                       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, struct ui_file *file)
268 {
269   fprintf_filtered (file, "Control Word:        %s",
270                    local_hex_string_custom (control, "04"));
271   fputs_filtered ("  ", file);
272   fprintf_filtered (file, " %s", (control & 0x0001) ? "IM" : "  ");
273   fprintf_filtered (file, " %s", (control & 0x0002) ? "DM" : "  ");
274   fprintf_filtered (file, " %s", (control & 0x0004) ? "ZM" : "  ");
275   fprintf_filtered (file, " %s", (control & 0x0008) ? "OM" : "  ");
276   fprintf_filtered (file, " %s", (control & 0x0010) ? "UM" : "  ");
277   fprintf_filtered (file, " %s", (control & 0x0020) ? "PM" : "  ");
278
279   fputs_filtered ("\n", file);
280
281   fputs_filtered ("                       PC: ", file);
282   switch ((control >> 8) & 3)
283     {
284     case 0:
285       fputs_filtered ("Single Precision (24-bits)\n", file);
286       break;
287     case 1:
288       fputs_filtered ("Reserved\n", file);
289       break;
290     case 2:
291       fputs_filtered ("Double Precision (53-bits)\n", file);
292       break;
293     case 3:
294       fputs_filtered ("Extended Precision (64-bits)\n", file);
295       break;
296     }
297       
298   fputs_filtered ("                       RC: ", file);
299   switch ((control >> 10) & 3)
300     {
301     case 0:
302       fputs_filtered ("Round to nearest\n", file);
303       break;
304     case 1:
305       fputs_filtered ("Round down\n", file);
306       break;
307     case 2:
308       fputs_filtered ("Round up\n", file);
309       break;
310     case 3:
311       fputs_filtered ("Round toward zero\n", file);
312       break;
313     }
314 }
315
316 /* Print out the i387 floating point state.  Note that we ignore FRAME
317    in the code below.  That's OK since floating-point registers are
318    never saved on the stack.  */
319
320 void
321 i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
322                        struct frame_info *frame, const char *args)
323 {
324   unsigned int fctrl;
325   unsigned int fstat;
326   unsigned int ftag;
327   unsigned int fiseg;
328   unsigned int fioff;
329   unsigned int foseg;
330   unsigned int fooff;
331   unsigned int fop;
332   int fpreg;
333   int top;
334
335   fctrl = read_register (FCTRL_REGNUM);
336   fstat = read_register (FSTAT_REGNUM);
337   ftag  = read_register (FTAG_REGNUM);
338   fiseg = read_register (FCS_REGNUM);
339   fioff = read_register (FCOFF_REGNUM);
340   foseg = read_register (FDS_REGNUM);
341   fooff = read_register (FDOFF_REGNUM);
342   fop   = read_register (FOP_REGNUM);
343   
344   top = ((fstat >> 11) & 7);
345
346   for (fpreg = 7; fpreg >= 0; fpreg--)
347     {
348       unsigned char raw[FPU_REG_RAW_SIZE];
349       int tag = (ftag >> (fpreg * 2)) & 3;
350       int i;
351
352       fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : "  ", fpreg);
353
354       switch (tag)
355         {
356         case 0:
357           fputs_filtered ("Valid   ", file);
358           break;
359         case 1:
360           fputs_filtered ("Zero    ", file);
361           break;
362         case 2:
363           fputs_filtered ("Special ", file);
364           break;
365         case 3:
366           fputs_filtered ("Empty   ", file);
367           break;
368         }
369
370       read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
371
372       fputs_filtered ("0x", file);
373       for (i = 9; i >= 0; i--)
374         fprintf_filtered (file, "%02x", raw[i]);
375
376       if (tag != 3)
377         print_i387_ext (raw, file);
378
379       fputs_filtered ("\n", file);
380     }
381
382   puts_filtered ("\n");
383
384   print_i387_status_word (fstat, file);
385   print_i387_control_word (fctrl, file);
386   fprintf_filtered (file, "Tag Word:            %s\n",
387                     local_hex_string_custom (ftag, "04"));
388   fprintf_filtered (file, "Instruction Pointer: %s:",
389                     local_hex_string_custom (fiseg, "02"));
390   fprintf_filtered (file, "%s\n", local_hex_string_custom (fioff, "08"));
391   fprintf_filtered (file, "Operand Pointer:     %s:",
392                     local_hex_string_custom (foseg, "02"));
393   fprintf_filtered (file, "%s\n", local_hex_string_custom (fooff, "08"));
394   fprintf_filtered (file, "Opcode:              %s\n",
395                     local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
396 }
397
398 /* FIXME: kettenis/2000-05-21: Right now more than a few i386 targets
399    define their own routines to manage the floating-point registers in
400    GDB's register array.  Most (if not all) of these targets use the
401    format used by the "fsave" instruction in their communication with
402    the OS.  They should all be converted to use the routines below.  */
403
404 /* At fsave_offset[REGNUM] you'll find the offset to the location in
405    the data structure used by the "fsave" instruction where GDB
406    register REGNUM is stored.  */
407
408 static int fsave_offset[] =
409 {
410   28 + 0 * FPU_REG_RAW_SIZE,    /* FP0_REGNUM through ...  */
411   28 + 1 * FPU_REG_RAW_SIZE,  
412   28 + 2 * FPU_REG_RAW_SIZE,  
413   28 + 3 * FPU_REG_RAW_SIZE,  
414   28 + 4 * FPU_REG_RAW_SIZE,  
415   28 + 5 * FPU_REG_RAW_SIZE,  
416   28 + 6 * FPU_REG_RAW_SIZE,  
417   28 + 7 * FPU_REG_RAW_SIZE,    /* ... FP7_REGNUM.  */
418   0,                            /* FCTRL_REGNUM (16 bits).  */
419   4,                            /* FSTAT_REGNUM (16 bits).  */
420   8,                            /* FTAG_REGNUM (16 bits).  */
421   16,                           /* FISEG_REGNUM (16 bits).  */
422   12,                           /* FIOFF_REGNUM.  */
423   24,                           /* FOSEG_REGNUM.  */
424   20,                           /* FOOFF_REGNUM.  */
425   18                            /* FOP_REGNUM (bottom 11 bits).  */
426 };
427
428 #define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
429 \f
430
431 /* Fill register REGNUM in GDB's register array with the appropriate
432    value from *FSAVE.  This function masks off any of the reserved
433    bits in *FSAVE.  */
434
435 void
436 i387_supply_register (int regnum, char *fsave)
437 {
438   /* Most of the FPU control registers occupy only 16 bits in
439      the fsave area.  Give those a special treatment.  */
440   if (regnum >= FPC_REGNUM
441       && regnum != FIOFF_REGNUM && regnum != FOOFF_REGNUM)
442     {
443       unsigned char val[4];
444
445       memcpy (val, FSAVE_ADDR (fsave, regnum), 2);
446       val[2] = val[3] = 0;
447       if (regnum == FOP_REGNUM)
448         val[1] &= ((1 << 3) - 1);
449       supply_register (regnum, val);
450     }
451   else
452     supply_register (regnum, FSAVE_ADDR (fsave, regnum));
453 }
454
455 /* Fill GDB's register array with the floating-point register values
456    in *FSAVE.  This function masks off any of the reserved
457    bits in *FSAVE.  */
458
459 void
460 i387_supply_fsave (char *fsave)
461 {
462   int i;
463
464   for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
465     i387_supply_register (i, fsave);
466 }
467
468 /* Fill register REGNUM (if it is a floating-point register) in *FSAVE
469    with the value in GDB's register array.  If REGNUM is -1, do this
470    for all registers.  This function doesn't touch any of the reserved
471    bits in *FSAVE.  */
472
473 void
474 i387_fill_fsave (char *fsave, int regnum)
475 {
476   int i;
477
478   for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
479     if (regnum == -1 || regnum == i)
480       {
481         /* Most of the FPU control registers occupy only 16 bits in
482            the fsave area.  Give those a special treatment.  */
483         if (i >= FPC_REGNUM
484             && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
485           {
486             unsigned char buf[4];
487
488             regcache_collect (i, buf);
489
490             if (i == FOP_REGNUM)
491               {
492                 /* The opcode occupies only 11 bits.  Make sure we
493                    don't touch the other bits.  */
494                 buf[1] &= ((1 << 3) - 1);
495                 buf[1] |= ((FSAVE_ADDR (fsave, i))[1] & ~((1 << 3) - 1));
496               }
497             memcpy (FSAVE_ADDR (fsave, i), buf, 2);
498           }
499         else
500           regcache_collect (i, FSAVE_ADDR (fsave, i));
501       }
502 }
503 \f
504
505 /* At fxsave_offset[REGNUM] you'll find the offset to the location in
506    the data structure used by the "fxsave" instruction where GDB
507    register REGNUM is stored.  */
508
509 static int fxsave_offset[] =
510 {
511   32,                           /* FP0_REGNUM through ...  */
512   48,
513   64,
514   80,
515   96,
516   112,
517   128,
518   144,                          /* ... FP7_REGNUM (80 bits each).  */
519   0,                            /* FCTRL_REGNUM (16 bits).  */
520   2,                            /* FSTAT_REGNUM (16 bits).  */
521   4,                            /* FTAG_REGNUM (16 bits).  */
522   12,                           /* FISEG_REGNUM (16 bits).  */
523   8,                            /* FIOFF_REGNUM.  */
524   20,                           /* FOSEG_REGNUM (16 bits).  */
525   16,                           /* FOOFF_REGNUM.  */
526   6,                            /* FOP_REGNUM (bottom 11 bits).  */
527   160,                          /* XMM0_REGNUM through ...  */
528   176,
529   192,
530   208,
531   224,
532   240,
533   256,
534   272,                          /* ... XMM7_REGNUM (128 bits each).  */
535   24,                           /* MXCSR_REGNUM.  */
536 };
537
538 #define FXSAVE_ADDR(fxsave, regnum) \
539   (fxsave + fxsave_offset[regnum - FP0_REGNUM])
540
541 static int i387_tag (unsigned char *raw);
542 \f
543
544 /* Fill GDB's register array with the floating-point and SSE register
545    values in *FXSAVE.  This function masks off any of the reserved
546    bits in *FXSAVE.  */
547
548 void
549 i387_supply_fxsave (char *fxsave)
550 {
551   int i, last_regnum = MXCSR_REGNUM;
552
553   if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
554     last_regnum = FOP_REGNUM;
555
556   for (i = FP0_REGNUM; i <= last_regnum; i++)
557     {
558       /* Most of the FPU control registers occupy only 16 bits in
559          the fxsave area.  Give those a special treatment.  */
560       if (i >= FPC_REGNUM && i < XMM0_REGNUM
561           && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
562         {
563           unsigned char val[4];
564
565           memcpy (val, FXSAVE_ADDR (fxsave, i), 2);
566           val[2] = val[3] = 0;
567           if (i == FOP_REGNUM)
568             val[1] &= ((1 << 3) - 1);
569           else if (i== FTAG_REGNUM)
570             {
571               /* The fxsave area contains a simplified version of the
572                  tag word.  We have to look at the actual 80-bit FP
573                  data to recreate the traditional i387 tag word.  */
574
575               unsigned long ftag = 0;
576               int fpreg;
577               int top;
578
579               top = (((FXSAVE_ADDR (fxsave, FSTAT_REGNUM))[1] >> 3) & 0x7);
580
581               for (fpreg = 7; fpreg >= 0; fpreg--)
582                 {
583                   int tag;
584
585                   if (val[0] & (1 << fpreg))
586                     {
587                       int regnum = (fpreg + 8 - top) % 8 + FP0_REGNUM;
588                       tag = i387_tag (FXSAVE_ADDR (fxsave, regnum));
589                     }
590                   else
591                     tag = 3;            /* Empty */
592
593                   ftag |= tag << (2 * fpreg);
594                 }
595               val[0] = ftag & 0xff;
596               val[1] = (ftag >> 8) & 0xff;
597             }
598           supply_register (i, val);
599         }
600       else
601         supply_register (i, FXSAVE_ADDR (fxsave, i));
602     }
603 }
604
605 /* Fill register REGNUM (if it is a floating-point or SSE register) in
606    *FXSAVE with the value in GDB's register array.  If REGNUM is -1, do
607    this for all registers.  This function doesn't touch any of the
608    reserved bits in *FXSAVE.  */
609
610 void
611 i387_fill_fxsave (char *fxsave, int regnum)
612 {
613   int i, last_regnum = MXCSR_REGNUM;
614
615   if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
616     last_regnum = FOP_REGNUM;
617
618   for (i = FP0_REGNUM; i <= last_regnum; i++)
619     if (regnum == -1 || regnum == i)
620       {
621         /* Most of the FPU control registers occupy only 16 bits in
622            the fxsave area.  Give those a special treatment.  */
623         if (i >= FPC_REGNUM && i < XMM0_REGNUM
624             && i != FIOFF_REGNUM && i != FDOFF_REGNUM)
625           {
626             unsigned char buf[4];
627
628             regcache_collect (i, buf);
629
630             if (i == FOP_REGNUM)
631               {
632                 /* The opcode occupies only 11 bits.  Make sure we
633                    don't touch the other bits.  */
634                 buf[1] &= ((1 << 3) - 1);
635                 buf[1] |= ((FXSAVE_ADDR (fxsave, i))[1] & ~((1 << 3) - 1));
636               }
637             else if (i == FTAG_REGNUM)
638               {
639                 /* Converting back is much easier.  */
640
641                 unsigned short ftag;
642                 int fpreg;
643
644                 ftag = (buf[1] << 8) | buf[0];
645                 buf[0] = 0;
646                 buf[1] = 0;
647
648                 for (fpreg = 7; fpreg >= 0; fpreg--)
649                   {
650                     int tag = (ftag >> (fpreg * 2)) & 3;
651
652                     if (tag != 3)
653                       buf[0] |= (1 << fpreg);
654                   }
655               }
656             memcpy (FXSAVE_ADDR (fxsave, i), buf, 2);
657           }
658         else
659           regcache_collect (i, FXSAVE_ADDR (fxsave, i));
660       }
661 }
662
663 /* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
664    *RAW.  */
665
666 static int
667 i387_tag (unsigned char *raw)
668 {
669   int integer;
670   unsigned int exponent;
671   unsigned long fraction[2];
672
673   integer = raw[7] & 0x80;
674   exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
675   fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
676   fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
677                  | (raw[5] << 8) | raw[4]);
678
679   if (exponent == 0x7fff)
680     {
681       /* Special.  */
682       return (2);
683     }
684   else if (exponent == 0x0000)
685     {
686       if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
687         {
688           /* Zero.  */
689           return (1);
690         }
691       else
692         {
693           /* Special.  */
694           return (2);
695         }
696     }
697   else
698     {
699       if (integer)
700         {
701           /* Valid.  */
702           return (0);
703         }
704       else
705         {
706           /* Special.  */
707           return (2);
708         }
709     }
710 }