GDB (API)
/home/stan/gdb/src/gdb/i387-tdep.c
Go to the documentation of this file.
00001 /* Intel 387 floating point stuff.
00002 
00003    Copyright (C) 1988-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "doublest.h"
00022 #include "floatformat.h"
00023 #include "frame.h"
00024 #include "gdbcore.h"
00025 #include "inferior.h"
00026 #include "language.h"
00027 #include "regcache.h"
00028 #include "value.h"
00029 
00030 #include "gdb_assert.h"
00031 #include "gdb_string.h"
00032 
00033 #include "i386-tdep.h"
00034 #include "i387-tdep.h"
00035 #include "i386-xstate.h"
00036 
00037 /* Print the floating point number specified by RAW.  */
00038 
00039 static void
00040 print_i387_value (struct gdbarch *gdbarch,
00041                   const gdb_byte *raw, struct ui_file *file)
00042 {
00043   DOUBLEST value;
00044 
00045   /* Using extract_typed_floating here might affect the representation
00046      of certain numbers such as NaNs, even if GDB is running natively.
00047      This is fine since our caller already detects such special
00048      numbers and we print the hexadecimal representation anyway.  */
00049   value = extract_typed_floating (raw, i387_ext_type (gdbarch));
00050 
00051   /* We try to print 19 digits.  The last digit may or may not contain
00052      garbage, but we'd better print one too many.  We need enough room
00053      to print the value, 1 position for the sign, 1 for the decimal
00054      point, 19 for the digits and 6 for the exponent adds up to 27.  */
00055 #ifdef PRINTF_HAS_LONG_DOUBLE
00056   fprintf_filtered (file, " %-+27.19Lg", (long double) value);
00057 #else
00058   fprintf_filtered (file, " %-+27.19g", (double) value);
00059 #endif
00060 }
00061 
00062 /* Print the classification for the register contents RAW.  */
00063 
00064 static void
00065 print_i387_ext (struct gdbarch *gdbarch,
00066                 const gdb_byte *raw, struct ui_file *file)
00067 {
00068   int sign;
00069   int integer;
00070   unsigned int exponent;
00071   unsigned long fraction[2];
00072 
00073   sign = raw[9] & 0x80;
00074   integer = raw[7] & 0x80;
00075   exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
00076   fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
00077   fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
00078                  | (raw[5] << 8) | raw[4]);
00079 
00080   if (exponent == 0x7fff && integer)
00081     {
00082       if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
00083         /* Infinity.  */
00084         fprintf_filtered (file, " %cInf", (sign ? '-' : '+'));
00085       else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
00086         /* Real Indefinite (QNaN).  */
00087         fputs_unfiltered (" Real Indefinite (QNaN)", file);
00088       else if (fraction[1] & 0x40000000)
00089         /* QNaN.  */
00090         fputs_filtered (" QNaN", file);
00091       else
00092         /* SNaN.  */
00093         fputs_filtered (" SNaN", file);
00094     }
00095   else if (exponent < 0x7fff && exponent > 0x0000 && integer)
00096     /* Normal.  */
00097     print_i387_value (gdbarch, raw, file);
00098   else if (exponent == 0x0000)
00099     {
00100       /* Denormal or zero.  */
00101       print_i387_value (gdbarch, raw, file);
00102       
00103       if (integer)
00104         /* Pseudo-denormal.  */
00105         fputs_filtered (" Pseudo-denormal", file);
00106       else if (fraction[0] || fraction[1])
00107         /* Denormal.  */
00108         fputs_filtered (" Denormal", file);
00109     }
00110   else
00111     /* Unsupported.  */
00112     fputs_filtered (" Unsupported", file);
00113 }
00114 
00115 /* Print the status word STATUS.  If STATUS_P is false, then STATUS
00116    was unavailable.  */
00117 
00118 static void
00119 print_i387_status_word (int status_p,
00120                         unsigned int status, struct ui_file *file)
00121 {
00122   fprintf_filtered (file, "Status Word:         ");
00123   if (!status_p)
00124     {
00125       fprintf_filtered (file, "%s\n", _("<unavailable>"));
00126       return;
00127     }
00128 
00129   fprintf_filtered (file, "%s", hex_string_custom (status, 4));
00130   fputs_filtered ("  ", file);
00131   fprintf_filtered (file, " %s", (status & 0x0001) ? "IE" : "  ");
00132   fprintf_filtered (file, " %s", (status & 0x0002) ? "DE" : "  ");
00133   fprintf_filtered (file, " %s", (status & 0x0004) ? "ZE" : "  ");
00134   fprintf_filtered (file, " %s", (status & 0x0008) ? "OE" : "  ");
00135   fprintf_filtered (file, " %s", (status & 0x0010) ? "UE" : "  ");
00136   fprintf_filtered (file, " %s", (status & 0x0020) ? "PE" : "  ");
00137   fputs_filtered ("  ", file);
00138   fprintf_filtered (file, " %s", (status & 0x0080) ? "ES" : "  ");
00139   fputs_filtered ("  ", file);
00140   fprintf_filtered (file, " %s", (status & 0x0040) ? "SF" : "  ");
00141   fputs_filtered ("  ", file);
00142   fprintf_filtered (file, " %s", (status & 0x0100) ? "C0" : "  ");
00143   fprintf_filtered (file, " %s", (status & 0x0200) ? "C1" : "  ");
00144   fprintf_filtered (file, " %s", (status & 0x0400) ? "C2" : "  ");
00145   fprintf_filtered (file, " %s", (status & 0x4000) ? "C3" : "  ");
00146 
00147   fputs_filtered ("\n", file);
00148 
00149   fprintf_filtered (file,
00150                     "                       TOP: %d\n", ((status >> 11) & 7));
00151 }
00152 
00153 /* Print the control word CONTROL.  If CONTROL_P is false, then
00154    CONTROL was unavailable.  */
00155 
00156 static void
00157 print_i387_control_word (int control_p,
00158                          unsigned int control, struct ui_file *file)
00159 {
00160   fprintf_filtered (file, "Control Word:        ");
00161   if (!control_p)
00162     {
00163       fprintf_filtered (file, "%s\n", _("<unavailable>"));
00164       return;
00165     }
00166 
00167   fprintf_filtered (file, "%s", hex_string_custom (control, 4));
00168   fputs_filtered ("  ", file);
00169   fprintf_filtered (file, " %s", (control & 0x0001) ? "IM" : "  ");
00170   fprintf_filtered (file, " %s", (control & 0x0002) ? "DM" : "  ");
00171   fprintf_filtered (file, " %s", (control & 0x0004) ? "ZM" : "  ");
00172   fprintf_filtered (file, " %s", (control & 0x0008) ? "OM" : "  ");
00173   fprintf_filtered (file, " %s", (control & 0x0010) ? "UM" : "  ");
00174   fprintf_filtered (file, " %s", (control & 0x0020) ? "PM" : "  ");
00175 
00176   fputs_filtered ("\n", file);
00177 
00178   fputs_filtered ("                       PC: ", file);
00179   switch ((control >> 8) & 3)
00180     {
00181     case 0:
00182       fputs_filtered ("Single Precision (24-bits)\n", file);
00183       break;
00184     case 1:
00185       fputs_filtered ("Reserved\n", file);
00186       break;
00187     case 2:
00188       fputs_filtered ("Double Precision (53-bits)\n", file);
00189       break;
00190     case 3:
00191       fputs_filtered ("Extended Precision (64-bits)\n", file);
00192       break;
00193     }
00194       
00195   fputs_filtered ("                       RC: ", file);
00196   switch ((control >> 10) & 3)
00197     {
00198     case 0:
00199       fputs_filtered ("Round to nearest\n", file);
00200       break;
00201     case 1:
00202       fputs_filtered ("Round down\n", file);
00203       break;
00204     case 2:
00205       fputs_filtered ("Round up\n", file);
00206       break;
00207     case 3:
00208       fputs_filtered ("Round toward zero\n", file);
00209       break;
00210     }
00211 }
00212 
00213 /* Print out the i387 floating point state.  Note that we ignore FRAME
00214    in the code below.  That's OK since floating-point registers are
00215    never saved on the stack.  */
00216 
00217 void
00218 i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
00219                        struct frame_info *frame, const char *args)
00220 {
00221   struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
00222   ULONGEST fctrl;
00223   int fctrl_p;
00224   ULONGEST fstat;
00225   int fstat_p;
00226   ULONGEST ftag;
00227   int ftag_p;
00228   ULONGEST fiseg;
00229   int fiseg_p;
00230   ULONGEST fioff;
00231   int fioff_p;
00232   ULONGEST foseg;
00233   int foseg_p;
00234   ULONGEST fooff;
00235   int fooff_p;
00236   ULONGEST fop;
00237   int fop_p;
00238   int fpreg;
00239   int top;
00240 
00241   gdb_assert (gdbarch == get_frame_arch (frame));
00242 
00243   fctrl_p = read_frame_register_unsigned (frame,
00244                                           I387_FCTRL_REGNUM (tdep), &fctrl);
00245   fstat_p = read_frame_register_unsigned (frame,
00246                                           I387_FSTAT_REGNUM (tdep), &fstat);
00247   ftag_p = read_frame_register_unsigned (frame,
00248                                          I387_FTAG_REGNUM (tdep), &ftag);
00249   fiseg_p = read_frame_register_unsigned (frame,
00250                                           I387_FISEG_REGNUM (tdep), &fiseg);
00251   fioff_p = read_frame_register_unsigned (frame,
00252                                           I387_FIOFF_REGNUM (tdep), &fioff);
00253   foseg_p = read_frame_register_unsigned (frame,
00254                                           I387_FOSEG_REGNUM (tdep), &foseg);
00255   fooff_p = read_frame_register_unsigned (frame,
00256                                           I387_FOOFF_REGNUM (tdep), &fooff);
00257   fop_p = read_frame_register_unsigned (frame,
00258                                         I387_FOP_REGNUM (tdep), &fop);
00259 
00260   if (fstat_p)
00261     {
00262       top = ((fstat >> 11) & 7);
00263 
00264       for (fpreg = 7; fpreg >= 0; fpreg--)
00265         {
00266           struct value *regval;
00267           int regnum;
00268           int i;
00269           int tag = -1;
00270 
00271           fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : "  ", fpreg);
00272 
00273           if (ftag_p)
00274             {
00275               tag = (ftag >> (fpreg * 2)) & 3;
00276 
00277               switch (tag)
00278                 {
00279                 case 0:
00280                   fputs_filtered ("Valid   ", file);
00281                   break;
00282                 case 1:
00283                   fputs_filtered ("Zero    ", file);
00284                   break;
00285                 case 2:
00286                   fputs_filtered ("Special ", file);
00287                   break;
00288                 case 3:
00289                   fputs_filtered ("Empty   ", file);
00290                   break;
00291                 }
00292             }
00293           else
00294             fputs_filtered ("Unknown ", file);
00295 
00296           regnum = (fpreg + 8 - top) % 8 + I387_ST0_REGNUM (tdep);
00297           regval = get_frame_register_value (frame, regnum);
00298 
00299           if (value_entirely_available (regval))
00300             {
00301               const gdb_byte *raw = value_contents (regval);
00302 
00303               fputs_filtered ("0x", file);
00304               for (i = 9; i >= 0; i--)
00305                 fprintf_filtered (file, "%02x", raw[i]);
00306 
00307               if (tag != -1 && tag != 3)
00308                 print_i387_ext (gdbarch, raw, file);
00309             }
00310           else
00311             fprintf_filtered (file, "%s", _("<unavailable>"));
00312 
00313           fputs_filtered ("\n", file);
00314         }
00315     }
00316 
00317   fputs_filtered ("\n", file);
00318   print_i387_status_word (fstat_p, fstat, file);
00319   print_i387_control_word (fctrl_p, fctrl, file);
00320   fprintf_filtered (file, "Tag Word:            %s\n",
00321                     ftag_p ? hex_string_custom (ftag, 4) : _("<unavailable>"));
00322   fprintf_filtered (file, "Instruction Pointer: %s:",
00323                     fiseg_p ? hex_string_custom (fiseg, 2) : _("<unavailable>"));
00324   fprintf_filtered (file, "%s\n",
00325                     fioff_p ? hex_string_custom (fioff, 8) : _("<unavailable>"));
00326   fprintf_filtered (file, "Operand Pointer:     %s:",
00327                     foseg_p ? hex_string_custom (foseg, 2) : _("<unavailable>"));
00328   fprintf_filtered (file, "%s\n",
00329                     fooff_p ? hex_string_custom (fooff, 8) : _("<unavailable>"));
00330   fprintf_filtered (file, "Opcode:              %s\n",
00331                     fop_p
00332                     ? (hex_string_custom (fop ? (fop | 0xd800) : 0, 4))
00333                     : _("<unavailable>"));
00334 }
00335 
00336 
00337 /* Return nonzero if a value of type TYPE stored in register REGNUM
00338    needs any special handling.  */
00339 
00340 int
00341 i387_convert_register_p (struct gdbarch *gdbarch, int regnum,
00342                          struct type *type)
00343 {
00344   if (i386_fp_regnum_p (gdbarch, regnum))
00345     {
00346       /* Floating point registers must be converted unless we are
00347          accessing them in their hardware type.  */
00348       if (type == i387_ext_type (gdbarch))
00349         return 0;
00350       else
00351         return 1;
00352     }
00353 
00354   return 0;
00355 }
00356 
00357 /* Read a value of type TYPE from register REGNUM in frame FRAME, and
00358    return its contents in TO.  */
00359 
00360 int
00361 i387_register_to_value (struct frame_info *frame, int regnum,
00362                         struct type *type, gdb_byte *to,
00363                         int *optimizedp, int *unavailablep)
00364 {
00365   struct gdbarch *gdbarch = get_frame_arch (frame);
00366   gdb_byte from[I386_MAX_REGISTER_SIZE];
00367 
00368   gdb_assert (i386_fp_regnum_p (gdbarch, regnum));
00369 
00370   /* We only support floating-point values.  */
00371   if (TYPE_CODE (type) != TYPE_CODE_FLT)
00372     {
00373       warning (_("Cannot convert floating-point register value "
00374                "to non-floating-point type."));
00375       *optimizedp = *unavailablep = 0;
00376       return 0;
00377     }
00378 
00379   /* Convert to TYPE.  */
00380   if (!get_frame_register_bytes (frame, regnum, 0, TYPE_LENGTH (type),
00381                                  from, optimizedp, unavailablep))
00382     return 0;
00383 
00384   convert_typed_floating (from, i387_ext_type (gdbarch), to, type);
00385   *optimizedp = *unavailablep = 0;
00386   return 1;
00387 }
00388 
00389 /* Write the contents FROM of a value of type TYPE into register
00390    REGNUM in frame FRAME.  */
00391 
00392 void
00393 i387_value_to_register (struct frame_info *frame, int regnum,
00394                         struct type *type, const gdb_byte *from)
00395 {
00396   struct gdbarch *gdbarch = get_frame_arch (frame);
00397   gdb_byte to[I386_MAX_REGISTER_SIZE];
00398 
00399   gdb_assert (i386_fp_regnum_p (gdbarch, regnum));
00400 
00401   /* We only support floating-point values.  */
00402   if (TYPE_CODE (type) != TYPE_CODE_FLT)
00403     {
00404       warning (_("Cannot convert non-floating-point type "
00405                "to floating-point register value."));
00406       return;
00407     }
00408 
00409   /* Convert from TYPE.  */
00410   convert_typed_floating (from, type, to, i387_ext_type (gdbarch));
00411   put_frame_register (frame, regnum, to);
00412 }
00413 
00414 
00415 /* Handle FSAVE and FXSAVE formats.  */
00416 
00417 /* At fsave_offset[REGNUM] you'll find the offset to the location in
00418    the data structure used by the "fsave" instruction where GDB
00419    register REGNUM is stored.  */
00420 
00421 static int fsave_offset[] =
00422 {
00423   28 + 0 * 10,                  /* %st(0) ...  */
00424   28 + 1 * 10,
00425   28 + 2 * 10,
00426   28 + 3 * 10,
00427   28 + 4 * 10,
00428   28 + 5 * 10,
00429   28 + 6 * 10,
00430   28 + 7 * 10,                  /* ... %st(7).  */
00431   0,                            /* `fctrl' (16 bits).  */
00432   4,                            /* `fstat' (16 bits).  */
00433   8,                            /* `ftag' (16 bits).  */
00434   16,                           /* `fiseg' (16 bits).  */
00435   12,                           /* `fioff'.  */
00436   24,                           /* `foseg' (16 bits).  */
00437   20,                           /* `fooff'.  */
00438   18                            /* `fop' (bottom 11 bits).  */
00439 };
00440 
00441 #define FSAVE_ADDR(tdep, fsave, regnum) \
00442   (fsave + fsave_offset[regnum - I387_ST0_REGNUM (tdep)])
00443 
00444 
00445 /* Fill register REGNUM in REGCACHE with the appropriate value from
00446    *FSAVE.  This function masks off any of the reserved bits in
00447    *FSAVE.  */
00448 
00449 void
00450 i387_supply_fsave (struct regcache *regcache, int regnum, const void *fsave)
00451 {
00452   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00453   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00454   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00455   const gdb_byte *regs = fsave;
00456   int i;
00457 
00458   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
00459 
00460   for (i = I387_ST0_REGNUM (tdep); i < I387_XMM0_REGNUM (tdep); i++)
00461     if (regnum == -1 || regnum == i)
00462       {
00463         if (fsave == NULL)
00464           {
00465             regcache_raw_supply (regcache, i, NULL);
00466             continue;
00467           }
00468 
00469         /* Most of the FPU control registers occupy only 16 bits in the
00470            fsave area.  Give those a special treatment.  */
00471         if (i >= I387_FCTRL_REGNUM (tdep)
00472             && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
00473           {
00474             gdb_byte val[4];
00475 
00476             memcpy (val, FSAVE_ADDR (tdep, regs, i), 2);
00477             val[2] = val[3] = 0;
00478             if (i == I387_FOP_REGNUM (tdep))
00479               val[1] &= ((1 << 3) - 1);
00480             regcache_raw_supply (regcache, i, val);
00481           }
00482         else
00483           regcache_raw_supply (regcache, i, FSAVE_ADDR (tdep, regs, i));
00484       }
00485 
00486   /* Provide dummy values for the SSE registers.  */
00487   for (i = I387_XMM0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
00488     if (regnum == -1 || regnum == i)
00489       regcache_raw_supply (regcache, i, NULL);
00490   if (regnum == -1 || regnum == I387_MXCSR_REGNUM (tdep))
00491     {
00492       gdb_byte buf[4];
00493 
00494       store_unsigned_integer (buf, 4, byte_order, 0x1f80);
00495       regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep), buf);
00496     }
00497 }
00498 
00499 /* Fill register REGNUM (if it is a floating-point register) in *FSAVE
00500    with the value from REGCACHE.  If REGNUM is -1, do this for all
00501    registers.  This function doesn't touch any of the reserved bits in
00502    *FSAVE.  */
00503 
00504 void
00505 i387_collect_fsave (const struct regcache *regcache, int regnum, void *fsave)
00506 {
00507   struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
00508   gdb_byte *regs = fsave;
00509   int i;
00510 
00511   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
00512 
00513   for (i = I387_ST0_REGNUM (tdep); i < I387_XMM0_REGNUM (tdep); i++)
00514     if (regnum == -1 || regnum == i)
00515       {
00516         /* Most of the FPU control registers occupy only 16 bits in
00517            the fsave area.  Give those a special treatment.  */
00518         if (i >= I387_FCTRL_REGNUM (tdep)
00519             && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
00520           {
00521             gdb_byte buf[4];
00522 
00523             regcache_raw_collect (regcache, i, buf);
00524 
00525             if (i == I387_FOP_REGNUM (tdep))
00526               {
00527                 /* The opcode occupies only 11 bits.  Make sure we
00528                    don't touch the other bits.  */
00529                 buf[1] &= ((1 << 3) - 1);
00530                 buf[1] |= ((FSAVE_ADDR (tdep, regs, i))[1] & ~((1 << 3) - 1));
00531               }
00532             memcpy (FSAVE_ADDR (tdep, regs, i), buf, 2);
00533           }
00534         else
00535           regcache_raw_collect (regcache, i, FSAVE_ADDR (tdep, regs, i));
00536       }
00537 }
00538 
00539 
00540 /* At fxsave_offset[REGNUM] you'll find the offset to the location in
00541    the data structure used by the "fxsave" instruction where GDB
00542    register REGNUM is stored.  */
00543 
00544 static int fxsave_offset[] =
00545 {
00546   32,                           /* %st(0) through ...  */
00547   48,
00548   64,
00549   80,
00550   96,
00551   112,
00552   128,
00553   144,                          /* ... %st(7) (80 bits each).  */
00554   0,                            /* `fctrl' (16 bits).  */
00555   2,                            /* `fstat' (16 bits).  */
00556   4,                            /* `ftag' (16 bits).  */
00557   12,                           /* `fiseg' (16 bits).  */
00558   8,                            /* `fioff'.  */
00559   20,                           /* `foseg' (16 bits).  */
00560   16,                           /* `fooff'.  */
00561   6,                            /* `fop' (bottom 11 bits).  */
00562   160 + 0 * 16,                 /* %xmm0 through ...  */
00563   160 + 1 * 16,
00564   160 + 2 * 16,
00565   160 + 3 * 16,
00566   160 + 4 * 16,
00567   160 + 5 * 16,
00568   160 + 6 * 16,
00569   160 + 7 * 16,
00570   160 + 8 * 16,
00571   160 + 9 * 16,
00572   160 + 10 * 16,
00573   160 + 11 * 16,
00574   160 + 12 * 16,
00575   160 + 13 * 16,
00576   160 + 14 * 16,
00577   160 + 15 * 16,                /* ... %xmm15 (128 bits each).  */
00578 };
00579 
00580 #define FXSAVE_ADDR(tdep, fxsave, regnum) \
00581   (fxsave + fxsave_offset[regnum - I387_ST0_REGNUM (tdep)])
00582 
00583 /* We made an unfortunate choice in putting %mxcsr after the SSE
00584    registers %xmm0-%xmm7 instead of before, since it makes supporting
00585    the registers %xmm8-%xmm15 on AMD64 a bit involved.  Therefore we
00586    don't include the offset for %mxcsr here above.  */
00587 
00588 #define FXSAVE_MXCSR_ADDR(fxsave) (fxsave + 24)
00589 
00590 static int i387_tag (const gdb_byte *raw);
00591 
00592 
00593 /* Fill register REGNUM in REGCACHE with the appropriate
00594    floating-point or SSE register value from *FXSAVE.  This function
00595    masks off any of the reserved bits in *FXSAVE.  */
00596 
00597 void
00598 i387_supply_fxsave (struct regcache *regcache, int regnum, const void *fxsave)
00599 {
00600   struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
00601   const gdb_byte *regs = fxsave;
00602   int i;
00603 
00604   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
00605   gdb_assert (tdep->num_xmm_regs > 0);
00606 
00607   for (i = I387_ST0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
00608     if (regnum == -1 || regnum == i)
00609       {
00610         if (regs == NULL)
00611           {
00612             regcache_raw_supply (regcache, i, NULL);
00613             continue;
00614           }
00615 
00616         /* Most of the FPU control registers occupy only 16 bits in
00617            the fxsave area.  Give those a special treatment.  */
00618         if (i >= I387_FCTRL_REGNUM (tdep) && i < I387_XMM0_REGNUM (tdep)
00619             && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
00620           {
00621             gdb_byte val[4];
00622 
00623             memcpy (val, FXSAVE_ADDR (tdep, regs, i), 2);
00624             val[2] = val[3] = 0;
00625             if (i == I387_FOP_REGNUM (tdep))
00626               val[1] &= ((1 << 3) - 1);
00627             else if (i== I387_FTAG_REGNUM (tdep))
00628               {
00629                 /* The fxsave area contains a simplified version of
00630                    the tag word.  We have to look at the actual 80-bit
00631                    FP data to recreate the traditional i387 tag word.  */
00632 
00633                 unsigned long ftag = 0;
00634                 int fpreg;
00635                 int top;
00636 
00637                 top = ((FXSAVE_ADDR (tdep, regs,
00638                                      I387_FSTAT_REGNUM (tdep)))[1] >> 3);
00639                 top &= 0x7;
00640 
00641                 for (fpreg = 7; fpreg >= 0; fpreg--)
00642                   {
00643                     int tag;
00644 
00645                     if (val[0] & (1 << fpreg))
00646                       {
00647                         int thisreg = (fpreg + 8 - top) % 8 
00648                                        + I387_ST0_REGNUM (tdep);
00649                         tag = i387_tag (FXSAVE_ADDR (tdep, regs, thisreg));
00650                       }
00651                     else
00652                       tag = 3;          /* Empty */
00653 
00654                     ftag |= tag << (2 * fpreg);
00655                   }
00656                 val[0] = ftag & 0xff;
00657                 val[1] = (ftag >> 8) & 0xff;
00658               }
00659             regcache_raw_supply (regcache, i, val);
00660           }
00661         else
00662           regcache_raw_supply (regcache, i, FXSAVE_ADDR (tdep, regs, i));
00663       }
00664 
00665   if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
00666     {
00667       if (regs == NULL)
00668         regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep), NULL);
00669       else
00670         regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep),
00671                              FXSAVE_MXCSR_ADDR (regs));
00672     }
00673 }
00674 
00675 /* Fill register REGNUM (if it is a floating-point or SSE register) in
00676    *FXSAVE with the value from REGCACHE.  If REGNUM is -1, do this for
00677    all registers.  This function doesn't touch any of the reserved
00678    bits in *FXSAVE.  */
00679 
00680 void
00681 i387_collect_fxsave (const struct regcache *regcache, int regnum, void *fxsave)
00682 {
00683   struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
00684   gdb_byte *regs = fxsave;
00685   int i;
00686 
00687   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
00688   gdb_assert (tdep->num_xmm_regs > 0);
00689 
00690   for (i = I387_ST0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
00691     if (regnum == -1 || regnum == i)
00692       {
00693         /* Most of the FPU control registers occupy only 16 bits in
00694            the fxsave area.  Give those a special treatment.  */
00695         if (i >= I387_FCTRL_REGNUM (tdep) && i < I387_XMM0_REGNUM (tdep)
00696             && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
00697           {
00698             gdb_byte buf[4];
00699 
00700             regcache_raw_collect (regcache, i, buf);
00701 
00702             if (i == I387_FOP_REGNUM (tdep))
00703               {
00704                 /* The opcode occupies only 11 bits.  Make sure we
00705                    don't touch the other bits.  */
00706                 buf[1] &= ((1 << 3) - 1);
00707                 buf[1] |= ((FXSAVE_ADDR (tdep, regs, i))[1] & ~((1 << 3) - 1));
00708               }
00709             else if (i == I387_FTAG_REGNUM (tdep))
00710               {
00711                 /* Converting back is much easier.  */
00712 
00713                 unsigned short ftag;
00714                 int fpreg;
00715 
00716                 ftag = (buf[1] << 8) | buf[0];
00717                 buf[0] = 0;
00718                 buf[1] = 0;
00719 
00720                 for (fpreg = 7; fpreg >= 0; fpreg--)
00721                   {
00722                     int tag = (ftag >> (fpreg * 2)) & 3;
00723 
00724                     if (tag != 3)
00725                       buf[0] |= (1 << fpreg);
00726                   }
00727               }
00728             memcpy (FXSAVE_ADDR (tdep, regs, i), buf, 2);
00729           }
00730         else
00731           regcache_raw_collect (regcache, i, FXSAVE_ADDR (tdep, regs, i));
00732       }
00733 
00734   if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
00735     regcache_raw_collect (regcache, I387_MXCSR_REGNUM (tdep),
00736                           FXSAVE_MXCSR_ADDR (regs));
00737 }
00738 
00739 /* `xstate_bv' is at byte offset 512.  */
00740 #define XSAVE_XSTATE_BV_ADDR(xsave) (xsave + 512)
00741 
00742 /* At xsave_avxh_offset[REGNUM] you'll find the offset to the location in
00743    the upper 128bit of AVX register data structure used by the "xsave"
00744    instruction where GDB register REGNUM is stored.  */
00745 
00746 static int xsave_avxh_offset[] =
00747 {
00748   576 + 0 * 16,         /* Upper 128bit of %ymm0 through ...  */
00749   576 + 1 * 16,
00750   576 + 2 * 16,
00751   576 + 3 * 16,
00752   576 + 4 * 16,
00753   576 + 5 * 16,
00754   576 + 6 * 16,
00755   576 + 7 * 16,
00756   576 + 8 * 16,
00757   576 + 9 * 16,
00758   576 + 10 * 16,
00759   576 + 11 * 16,
00760   576 + 12 * 16,
00761   576 + 13 * 16,
00762   576 + 14 * 16,
00763   576 + 15 * 16         /* Upper 128bit of ... %ymm15 (128 bits each).  */
00764 };
00765 
00766 #define XSAVE_AVXH_ADDR(tdep, xsave, regnum) \
00767   (xsave + xsave_avxh_offset[regnum - I387_YMM0H_REGNUM (tdep)])
00768 
00769 /* Similar to i387_supply_fxsave, but use XSAVE extended state.  */
00770 
00771 void
00772 i387_supply_xsave (struct regcache *regcache, int regnum,
00773                    const void *xsave)
00774 {
00775   struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
00776   const gdb_byte *regs = xsave;
00777   int i;
00778   unsigned int clear_bv;
00779   static const gdb_byte zero[MAX_REGISTER_SIZE] = { 0 };
00780   enum
00781     {
00782       none = 0x0,
00783       x87 = 0x1,
00784       sse = 0x2,
00785       avxh = 0x4,
00786       all = x87 | sse | avxh
00787     } regclass;
00788 
00789   gdb_assert (regs != NULL);
00790   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
00791   gdb_assert (tdep->num_xmm_regs > 0);
00792 
00793   if (regnum == -1)
00794     regclass = all;
00795   else if (regnum >= I387_YMM0H_REGNUM (tdep)
00796            && regnum < I387_YMMENDH_REGNUM (tdep))
00797     regclass = avxh;
00798   else if (regnum >= I387_XMM0_REGNUM(tdep)
00799            && regnum < I387_MXCSR_REGNUM (tdep))
00800     regclass = sse;
00801   else if (regnum >= I387_ST0_REGNUM (tdep)
00802            && regnum < I387_FCTRL_REGNUM (tdep))
00803     regclass = x87;
00804   else
00805     regclass = none;
00806 
00807   if (regclass != none)
00808     {
00809       /* Get `xstat_bv'.  */
00810       const gdb_byte *xstate_bv_p = XSAVE_XSTATE_BV_ADDR (regs);
00811 
00812       /* The supported bits in `xstat_bv' are 1 byte.  Clear part in
00813          vector registers if its bit in xstat_bv is zero.  */
00814       clear_bv = (~(*xstate_bv_p)) & tdep->xcr0;
00815     }
00816   else
00817     clear_bv = I386_XSTATE_AVX_MASK;
00818 
00819   /* With the delayed xsave mechanism, in between the program
00820      starting, and the program accessing the vector registers for the
00821      first time, the register's values are invalid.  The kernel
00822      initializes register states to zero when they are set the first
00823      time in a program.  This means that from the user-space programs'
00824      perspective, it's the same as if the registers have always been
00825      zero from the start of the program.  Therefore, the debugger
00826      should provide the same illusion to the user.  */
00827 
00828   switch (regclass)
00829     {
00830     case none:
00831       break;
00832 
00833     case avxh:
00834       if ((clear_bv & I386_XSTATE_AVX))
00835         regcache_raw_supply (regcache, regnum, zero);
00836       else
00837         regcache_raw_supply (regcache, regnum,
00838                              XSAVE_AVXH_ADDR (tdep, regs, regnum));
00839       return;
00840 
00841     case sse:
00842       if ((clear_bv & I386_XSTATE_SSE))
00843         regcache_raw_supply (regcache, regnum, zero);
00844       else
00845         regcache_raw_supply (regcache, regnum,
00846                              FXSAVE_ADDR (tdep, regs, regnum));
00847       return;
00848 
00849     case x87:
00850       if ((clear_bv & I386_XSTATE_X87))
00851         regcache_raw_supply (regcache, regnum, zero);
00852       else
00853         regcache_raw_supply (regcache, regnum,
00854                              FXSAVE_ADDR (tdep, regs, regnum));
00855       return;
00856 
00857     case all:
00858       /* Handle the upper YMM registers.  */
00859       if ((tdep->xcr0 & I386_XSTATE_AVX))
00860         {
00861           if ((clear_bv & I386_XSTATE_AVX))
00862             {
00863               for (i = I387_YMM0H_REGNUM (tdep);
00864                    i < I387_YMMENDH_REGNUM (tdep);
00865                    i++)
00866                 regcache_raw_supply (regcache, i, zero);
00867             }
00868           else
00869             {
00870               for (i = I387_YMM0H_REGNUM (tdep);
00871                    i < I387_YMMENDH_REGNUM (tdep);
00872                    i++)
00873                 regcache_raw_supply (regcache, i,
00874                                      XSAVE_AVXH_ADDR (tdep, regs, i));
00875             }
00876         }
00877 
00878       /* Handle the XMM registers.  */
00879       if ((tdep->xcr0 & I386_XSTATE_SSE))
00880         {
00881           if ((clear_bv & I386_XSTATE_SSE))
00882             {
00883               for (i = I387_XMM0_REGNUM (tdep);
00884                    i < I387_MXCSR_REGNUM (tdep);
00885                    i++)
00886                 regcache_raw_supply (regcache, i, zero);
00887             }
00888           else
00889             {
00890               for (i = I387_XMM0_REGNUM (tdep);
00891                    i < I387_MXCSR_REGNUM (tdep); i++)
00892                 regcache_raw_supply (regcache, i,
00893                                      FXSAVE_ADDR (tdep, regs, i));
00894             }
00895         }
00896 
00897       /* Handle the x87 registers.  */
00898       if ((tdep->xcr0 & I386_XSTATE_X87))
00899         {
00900           if ((clear_bv & I386_XSTATE_X87))
00901             {
00902               for (i = I387_ST0_REGNUM (tdep);
00903                    i < I387_FCTRL_REGNUM (tdep);
00904                    i++)
00905                 regcache_raw_supply (regcache, i, zero);
00906             }
00907           else
00908             {
00909               for (i = I387_ST0_REGNUM (tdep);
00910                    i < I387_FCTRL_REGNUM (tdep);
00911                    i++)
00912                 regcache_raw_supply (regcache, i, FXSAVE_ADDR (tdep, regs, i));
00913             }
00914         }
00915       break;
00916     }
00917 
00918   /* Only handle x87 control registers.  */
00919   for (i = I387_FCTRL_REGNUM (tdep); i < I387_XMM0_REGNUM (tdep); i++)
00920     if (regnum == -1 || regnum == i)
00921       {
00922         /* Most of the FPU control registers occupy only 16 bits in
00923            the xsave extended state.  Give those a special treatment.  */
00924         if (i != I387_FIOFF_REGNUM (tdep)
00925             && i != I387_FOOFF_REGNUM (tdep))
00926           {
00927             gdb_byte val[4];
00928 
00929             memcpy (val, FXSAVE_ADDR (tdep, regs, i), 2);
00930             val[2] = val[3] = 0;
00931             if (i == I387_FOP_REGNUM (tdep))
00932               val[1] &= ((1 << 3) - 1);
00933             else if (i== I387_FTAG_REGNUM (tdep))
00934               {
00935                 /* The fxsave area contains a simplified version of
00936                    the tag word.  We have to look at the actual 80-bit
00937                    FP data to recreate the traditional i387 tag word.  */
00938 
00939                 unsigned long ftag = 0;
00940                 int fpreg;
00941                 int top;
00942 
00943                 top = ((FXSAVE_ADDR (tdep, regs,
00944                                      I387_FSTAT_REGNUM (tdep)))[1] >> 3);
00945                 top &= 0x7;
00946 
00947                 for (fpreg = 7; fpreg >= 0; fpreg--)
00948                   {
00949                     int tag;
00950 
00951                     if (val[0] & (1 << fpreg))
00952                       {
00953                         int thisreg = (fpreg + 8 - top) % 8 
00954                                        + I387_ST0_REGNUM (tdep);
00955                         tag = i387_tag (FXSAVE_ADDR (tdep, regs, thisreg));
00956                       }
00957                     else
00958                       tag = 3;          /* Empty */
00959 
00960                     ftag |= tag << (2 * fpreg);
00961                   }
00962                 val[0] = ftag & 0xff;
00963                 val[1] = (ftag >> 8) & 0xff;
00964               }
00965             regcache_raw_supply (regcache, i, val);
00966           }
00967         else 
00968           regcache_raw_supply (regcache, i, FXSAVE_ADDR (tdep, regs, i));
00969       }
00970 
00971   if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
00972     regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep),
00973                          FXSAVE_MXCSR_ADDR (regs));
00974 }
00975 
00976 /* Similar to i387_collect_fxsave, but use XSAVE extended state.  */
00977 
00978 void
00979 i387_collect_xsave (const struct regcache *regcache, int regnum,
00980                     void *xsave, int gcore)
00981 {
00982   struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
00983   gdb_byte *regs = xsave;
00984   int i;
00985   enum
00986     {
00987       none = 0x0,
00988       check = 0x1,
00989       x87 = 0x2 | check,
00990       sse = 0x4 | check,
00991       avxh = 0x8 | check,
00992       all = x87 | sse | avxh
00993     } regclass;
00994 
00995   gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
00996   gdb_assert (tdep->num_xmm_regs > 0);
00997 
00998   if (regnum == -1)
00999     regclass = all;
01000   else if (regnum >= I387_YMM0H_REGNUM (tdep)
01001            && regnum < I387_YMMENDH_REGNUM (tdep))
01002     regclass = avxh;
01003   else if (regnum >= I387_XMM0_REGNUM(tdep)
01004            && regnum < I387_MXCSR_REGNUM (tdep))
01005     regclass = sse;
01006   else if (regnum >= I387_ST0_REGNUM (tdep)
01007            && regnum < I387_FCTRL_REGNUM (tdep))
01008     regclass = x87;
01009   else
01010     regclass = none;
01011 
01012   if (gcore)
01013     {
01014       /* Clear XSAVE extended state.  */
01015       memset (regs, 0, I386_XSTATE_SIZE (tdep->xcr0));
01016 
01017       /* Update XCR0 and `xstate_bv' with XCR0 for gcore.  */
01018       if (tdep->xsave_xcr0_offset != -1)
01019         memcpy (regs + tdep->xsave_xcr0_offset, &tdep->xcr0, 8);
01020       memcpy (XSAVE_XSTATE_BV_ADDR (regs), &tdep->xcr0, 8);
01021     }
01022 
01023   if ((regclass & check))
01024     {
01025       gdb_byte raw[I386_MAX_REGISTER_SIZE];
01026       gdb_byte *xstate_bv_p = XSAVE_XSTATE_BV_ADDR (regs);
01027       unsigned int xstate_bv = 0;
01028       /* The supported bits in `xstat_bv' are 1 byte.  */
01029       unsigned int clear_bv = (~(*xstate_bv_p)) & tdep->xcr0;
01030       gdb_byte *p;
01031 
01032       /* Clear register set if its bit in xstat_bv is zero.  */
01033       if (clear_bv)
01034         {
01035           if ((clear_bv & I386_XSTATE_AVX))
01036             for (i = I387_YMM0H_REGNUM (tdep);
01037                  i < I387_YMMENDH_REGNUM (tdep); i++)
01038               memset (XSAVE_AVXH_ADDR (tdep, regs, i), 0, 16);
01039 
01040           if ((clear_bv & I386_XSTATE_SSE))
01041             for (i = I387_XMM0_REGNUM (tdep);
01042                  i < I387_MXCSR_REGNUM (tdep); i++)
01043               memset (FXSAVE_ADDR (tdep, regs, i), 0, 16);
01044 
01045           if ((clear_bv & I386_XSTATE_X87))
01046             for (i = I387_ST0_REGNUM (tdep);
01047                  i < I387_FCTRL_REGNUM (tdep); i++)
01048               memset (FXSAVE_ADDR (tdep, regs, i), 0, 10);
01049         }
01050 
01051       if (regclass == all)
01052         {
01053           /* Check if any upper YMM registers are changed.  */
01054           if ((tdep->xcr0 & I386_XSTATE_AVX))
01055             for (i = I387_YMM0H_REGNUM (tdep);
01056                  i < I387_YMMENDH_REGNUM (tdep); i++)
01057               {
01058                 regcache_raw_collect (regcache, i, raw);
01059                 p = XSAVE_AVXH_ADDR (tdep, regs, i);
01060                 if (memcmp (raw, p, 16))
01061                   {
01062                     xstate_bv |= I386_XSTATE_AVX;
01063                     memcpy (p, raw, 16);
01064                   }
01065               }
01066 
01067           /* Check if any SSE registers are changed.  */
01068           if ((tdep->xcr0 & I386_XSTATE_SSE))
01069             for (i = I387_XMM0_REGNUM (tdep);
01070                  i < I387_MXCSR_REGNUM (tdep); i++)
01071               {
01072                 regcache_raw_collect (regcache, i, raw);
01073                 p = FXSAVE_ADDR (tdep, regs, i);
01074                 if (memcmp (raw, p, 16))
01075                   {
01076                     xstate_bv |= I386_XSTATE_SSE;
01077                     memcpy (p, raw, 16);
01078                   }
01079               }
01080 
01081           /* Check if any X87 registers are changed.  */
01082           if ((tdep->xcr0 & I386_XSTATE_X87))
01083             for (i = I387_ST0_REGNUM (tdep);
01084                  i < I387_FCTRL_REGNUM (tdep); i++)
01085               {
01086                 regcache_raw_collect (regcache, i, raw);
01087                 p = FXSAVE_ADDR (tdep, regs, i);
01088                 if (memcmp (raw, p, 10))
01089                   {
01090                     xstate_bv |= I386_XSTATE_X87;
01091                     memcpy (p, raw, 10);
01092                   }
01093               }
01094         }
01095       else
01096         {
01097           /* Check if REGNUM is changed.  */
01098           regcache_raw_collect (regcache, regnum, raw);
01099 
01100           switch (regclass)
01101             {
01102             default:
01103               internal_error (__FILE__, __LINE__,
01104                               _("invalid i387 regclass"));
01105 
01106             case avxh:
01107               /* This is an upper YMM register.  */
01108               p = XSAVE_AVXH_ADDR (tdep, regs, regnum);
01109               if (memcmp (raw, p, 16))
01110                 {
01111                   xstate_bv |= I386_XSTATE_AVX;
01112                   memcpy (p, raw, 16);
01113                 }
01114               break;
01115 
01116             case sse:
01117               /* This is an SSE register.  */
01118               p = FXSAVE_ADDR (tdep, regs, regnum);
01119               if (memcmp (raw, p, 16))
01120                 {
01121                   xstate_bv |= I386_XSTATE_SSE;
01122                   memcpy (p, raw, 16);
01123                 }
01124               break;
01125 
01126             case x87:
01127               /* This is an x87 register.  */
01128               p = FXSAVE_ADDR (tdep, regs, regnum);
01129               if (memcmp (raw, p, 10))
01130                 {
01131                   xstate_bv |= I386_XSTATE_X87;
01132                   memcpy (p, raw, 10);
01133                 }
01134               break;
01135             }
01136         }
01137 
01138       /* Update the corresponding bits in `xstate_bv' if any SSE/AVX
01139          registers are changed.  */
01140       if (xstate_bv)
01141         {
01142           /* The supported bits in `xstat_bv' are 1 byte.  */
01143           *xstate_bv_p |= (gdb_byte) xstate_bv;
01144 
01145           switch (regclass)
01146             {
01147             default:
01148               internal_error (__FILE__, __LINE__,
01149                               _("invalid i387 regclass"));
01150 
01151             case all:
01152               break;
01153 
01154             case x87:
01155             case sse:
01156             case avxh:
01157               /* Register REGNUM has been updated.  Return.  */
01158               return;
01159             }
01160         }
01161       else
01162         {
01163           /* Return if REGNUM isn't changed.  */
01164           if (regclass != all)
01165             return;
01166         }
01167     }
01168 
01169   /* Only handle x87 control registers.  */
01170   for (i = I387_FCTRL_REGNUM (tdep); i < I387_XMM0_REGNUM (tdep); i++)
01171     if (regnum == -1 || regnum == i)
01172       {
01173         /* Most of the FPU control registers occupy only 16 bits in
01174            the xsave extended state.  Give those a special treatment.  */
01175         if (i != I387_FIOFF_REGNUM (tdep)
01176             && i != I387_FOOFF_REGNUM (tdep))
01177           {
01178             gdb_byte buf[4];
01179 
01180             regcache_raw_collect (regcache, i, buf);
01181 
01182             if (i == I387_FOP_REGNUM (tdep))
01183               {
01184                 /* The opcode occupies only 11 bits.  Make sure we
01185                    don't touch the other bits.  */
01186                 buf[1] &= ((1 << 3) - 1);
01187                 buf[1] |= ((FXSAVE_ADDR (tdep, regs, i))[1] & ~((1 << 3) - 1));
01188               }
01189             else if (i == I387_FTAG_REGNUM (tdep))
01190               {
01191                 /* Converting back is much easier.  */
01192 
01193                 unsigned short ftag;
01194                 int fpreg;
01195 
01196                 ftag = (buf[1] << 8) | buf[0];
01197                 buf[0] = 0;
01198                 buf[1] = 0;
01199 
01200                 for (fpreg = 7; fpreg >= 0; fpreg--)
01201                   {
01202                     int tag = (ftag >> (fpreg * 2)) & 3;
01203 
01204                     if (tag != 3)
01205                       buf[0] |= (1 << fpreg);
01206                   }
01207               }
01208             memcpy (FXSAVE_ADDR (tdep, regs, i), buf, 2);
01209           }
01210         else
01211           regcache_raw_collect (regcache, i, FXSAVE_ADDR (tdep, regs, i));
01212       }
01213 
01214   if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
01215     regcache_raw_collect (regcache, I387_MXCSR_REGNUM (tdep),
01216                           FXSAVE_MXCSR_ADDR (regs));
01217 }
01218 
01219 /* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
01220    *RAW.  */
01221 
01222 static int
01223 i387_tag (const gdb_byte *raw)
01224 {
01225   int integer;
01226   unsigned int exponent;
01227   unsigned long fraction[2];
01228 
01229   integer = raw[7] & 0x80;
01230   exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
01231   fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
01232   fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
01233                  | (raw[5] << 8) | raw[4]);
01234 
01235   if (exponent == 0x7fff)
01236     {
01237       /* Special.  */
01238       return (2);
01239     }
01240   else if (exponent == 0x0000)
01241     {
01242       if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
01243         {
01244           /* Zero.  */
01245           return (1);
01246         }
01247       else
01248         {
01249           /* Special.  */
01250           return (2);
01251         }
01252     }
01253   else
01254     {
01255       if (integer)
01256         {
01257           /* Valid.  */
01258           return (0);
01259         }
01260       else
01261         {
01262           /* Special.  */
01263           return (2);
01264         }
01265     }
01266 }
01267 
01268 /* Prepare the FPU stack in REGCACHE for a function return.  */
01269 
01270 void
01271 i387_return_value (struct gdbarch *gdbarch, struct regcache *regcache)
01272 {
01273   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
01274   ULONGEST fstat;
01275 
01276   /* Set the top of the floating-point register stack to 7.  The
01277      actual value doesn't really matter, but 7 is what a normal
01278      function return would end up with if the program started out with
01279      a freshly initialized FPU.  */
01280   regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM (tdep), &fstat);
01281   fstat |= (7 << 11);
01282   regcache_raw_write_unsigned (regcache, I387_FSTAT_REGNUM (tdep), fstat);
01283 
01284   /* Mark %st(1) through %st(7) as empty.  Since we set the top of the
01285      floating-point register stack to 7, the appropriate value for the
01286      tag word is 0x3fff.  */
01287   regcache_raw_write_unsigned (regcache, I387_FTAG_REGNUM (tdep), 0x3fff);
01288 
01289 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines