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