GDBserver
/home/stan/gdb/src/gdb/gdbserver/i387-fp.c
Go to the documentation of this file.
00001 /* i387-specific utility functions, for the remote server for GDB.
00002    Copyright (C) 2000-2013 Free Software Foundation, Inc.
00003 
00004    This file is part of GDB.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 3 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00018 
00019 #include "server.h"
00020 #include "i387-fp.h"
00021 #include "i386-xstate.h"
00022 
00023 /* Note: These functions preserve the reserved bits in control registers.
00024    However, gdbserver promptly throws away that information.  */
00025 
00026 /* These structs should have the proper sizes and alignment on both
00027    i386 and x86-64 machines.  */
00028 
00029 struct i387_fsave {
00030   /* All these are only sixteen bits, plus padding, except for fop (which
00031      is only eleven bits), and fooff / fioff (which are 32 bits each).  */
00032   unsigned short fctrl;
00033   unsigned short pad1;
00034   unsigned short fstat;
00035   unsigned short pad2;
00036   unsigned short ftag;
00037   unsigned short pad3;
00038   unsigned int fioff;
00039   unsigned short fiseg;
00040   unsigned short fop;
00041   unsigned int fooff;
00042   unsigned short foseg;
00043   unsigned short pad4;
00044 
00045   /* Space for eight 80-bit FP values.  */
00046   unsigned char st_space[80];
00047 };
00048 
00049 struct i387_fxsave {
00050   /* All these are only sixteen bits, plus padding, except for fop (which
00051      is only eleven bits), and fooff / fioff (which are 32 bits each).  */
00052   unsigned short fctrl;
00053   unsigned short fstat;
00054   unsigned short ftag;
00055   unsigned short fop;
00056   unsigned int fioff;
00057   unsigned short fiseg;
00058   unsigned short pad1;
00059   unsigned int fooff;
00060   unsigned short foseg;
00061   unsigned short pad12;
00062 
00063   unsigned int mxcsr;
00064   unsigned int pad3;
00065 
00066   /* Space for eight 80-bit FP values in 128-bit spaces.  */
00067   unsigned char st_space[128];
00068 
00069   /* Space for eight 128-bit XMM values, or 16 on x86-64.  */
00070   unsigned char xmm_space[256];
00071 };
00072 
00073 struct i387_xsave {
00074   /* All these are only sixteen bits, plus padding, except for fop (which
00075      is only eleven bits), and fooff / fioff (which are 32 bits each).  */
00076   unsigned short fctrl;
00077   unsigned short fstat;
00078   unsigned short ftag;
00079   unsigned short fop;
00080   unsigned int fioff;
00081   unsigned short fiseg;
00082   unsigned short pad1;
00083   unsigned int fooff;
00084   unsigned short foseg;
00085   unsigned short pad12;
00086 
00087   unsigned int mxcsr;
00088   unsigned int mxcsr_mask;
00089 
00090   /* Space for eight 80-bit FP values in 128-bit spaces.  */
00091   unsigned char st_space[128];
00092 
00093   /* Space for eight 128-bit XMM values, or 16 on x86-64.  */
00094   unsigned char xmm_space[256];
00095 
00096   unsigned char reserved1[48];
00097 
00098   /* The extended control register 0 (the XFEATURE_ENABLED_MASK
00099      register).  */
00100   unsigned long long xcr0;
00101 
00102   unsigned char reserved2[40];
00103 
00104   /* The XSTATE_BV bit vector.  */
00105   unsigned long long xstate_bv;
00106 
00107   unsigned char reserved3[56];
00108 
00109   /* Space for eight upper 128-bit YMM values, or 16 on x86-64.  */
00110   unsigned char ymmh_space[256];
00111 };
00112 
00113 void
00114 i387_cache_to_fsave (struct regcache *regcache, void *buf)
00115 {
00116   struct i387_fsave *fp = (struct i387_fsave *) buf;
00117   int i;
00118   int st0_regnum = find_regno (regcache->tdesc, "st0");
00119   unsigned long val, val2;
00120 
00121   for (i = 0; i < 8; i++)
00122     collect_register (regcache, i + st0_regnum,
00123                       ((char *) &fp->st_space[0]) + i * 10);
00124 
00125   collect_register_by_name (regcache, "fioff", &fp->fioff);
00126   collect_register_by_name (regcache, "fooff", &fp->fooff);
00127   
00128   /* This one's 11 bits... */
00129   collect_register_by_name (regcache, "fop", &val2);
00130   fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
00131 
00132   /* Some registers are 16-bit.  */
00133   collect_register_by_name (regcache, "fctrl", &val);
00134   fp->fctrl = val;
00135 
00136   collect_register_by_name (regcache, "fstat", &val);
00137   val &= 0xFFFF;
00138   fp->fstat = val;
00139 
00140   collect_register_by_name (regcache, "ftag", &val);
00141   val &= 0xFFFF;
00142   fp->ftag = val;
00143 
00144   collect_register_by_name (regcache, "fiseg", &val);
00145   val &= 0xFFFF;
00146   fp->fiseg = val;
00147 
00148   collect_register_by_name (regcache, "foseg", &val);
00149   val &= 0xFFFF;
00150   fp->foseg = val;
00151 }
00152 
00153 void
00154 i387_fsave_to_cache (struct regcache *regcache, const void *buf)
00155 {
00156   struct i387_fsave *fp = (struct i387_fsave *) buf;
00157   int i;
00158   int st0_regnum = find_regno (regcache->tdesc, "st0");
00159   unsigned long val;
00160 
00161   for (i = 0; i < 8; i++)
00162     supply_register (regcache, i + st0_regnum,
00163                      ((char *) &fp->st_space[0]) + i * 10);
00164 
00165   supply_register_by_name (regcache, "fioff", &fp->fioff);
00166   supply_register_by_name (regcache, "fooff", &fp->fooff);
00167 
00168   /* Some registers are 16-bit.  */
00169   val = fp->fctrl & 0xFFFF;
00170   supply_register_by_name (regcache, "fctrl", &val);
00171 
00172   val = fp->fstat & 0xFFFF;
00173   supply_register_by_name (regcache, "fstat", &val);
00174 
00175   val = fp->ftag & 0xFFFF;
00176   supply_register_by_name (regcache, "ftag", &val);
00177 
00178   val = fp->fiseg & 0xFFFF;
00179   supply_register_by_name (regcache, "fiseg", &val);
00180 
00181   val = fp->foseg & 0xFFFF;
00182   supply_register_by_name (regcache, "foseg", &val);
00183 
00184   /* fop has only 11 valid bits.  */
00185   val = (fp->fop) & 0x7FF;
00186   supply_register_by_name (regcache, "fop", &val);
00187 }
00188 
00189 void
00190 i387_cache_to_fxsave (struct regcache *regcache, void *buf)
00191 {
00192   struct i387_fxsave *fp = (struct i387_fxsave *) buf;
00193   int i;
00194   int st0_regnum = find_regno (regcache->tdesc, "st0");
00195   int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
00196   unsigned long val, val2;
00197   /* Amd64 has 16 xmm regs; I386 has 8 xmm regs.  */
00198   int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
00199 
00200   for (i = 0; i < 8; i++)
00201     collect_register (regcache, i + st0_regnum,
00202                       ((char *) &fp->st_space[0]) + i * 16);
00203   for (i = 0; i < num_xmm_registers; i++)
00204     collect_register (regcache, i + xmm0_regnum,
00205                       ((char *) &fp->xmm_space[0]) + i * 16);
00206 
00207   collect_register_by_name (regcache, "fioff", &fp->fioff);
00208   collect_register_by_name (regcache, "fooff", &fp->fooff);
00209   collect_register_by_name (regcache, "mxcsr", &fp->mxcsr);
00210 
00211   /* This one's 11 bits... */
00212   collect_register_by_name (regcache, "fop", &val2);
00213   fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
00214 
00215   /* Some registers are 16-bit.  */
00216   collect_register_by_name (regcache, "fctrl", &val);
00217   fp->fctrl = val;
00218 
00219   collect_register_by_name (regcache, "fstat", &val);
00220   fp->fstat = val;
00221 
00222   /* Convert to the simplifed tag form stored in fxsave data.  */
00223   collect_register_by_name (regcache, "ftag", &val);
00224   val &= 0xFFFF;
00225   val2 = 0;
00226   for (i = 7; i >= 0; i--)
00227     {
00228       int tag = (val >> (i * 2)) & 3;
00229 
00230       if (tag != 3)
00231         val2 |= (1 << i);
00232     }
00233   fp->ftag = val2;
00234 
00235   collect_register_by_name (regcache, "fiseg", &val);
00236   fp->fiseg = val;
00237 
00238   collect_register_by_name (regcache, "foseg", &val);
00239   fp->foseg = val;
00240 }
00241 
00242 void
00243 i387_cache_to_xsave (struct regcache *regcache, void *buf)
00244 {
00245   struct i387_xsave *fp = (struct i387_xsave *) buf;
00246   int i;
00247   unsigned long val, val2;
00248   unsigned int clear_bv;
00249   unsigned long long xstate_bv = 0;
00250   char raw[16];
00251   char *p;
00252   /* Amd64 has 16 xmm regs; I386 has 8 xmm regs.  */
00253   int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
00254 
00255   /* The supported bits in `xstat_bv' are 1 byte.  Clear part in
00256      vector registers if its bit in xstat_bv is zero.  */
00257   clear_bv = (~fp->xstate_bv) & x86_xcr0;
00258 
00259   /* Clear part in x87 and vector registers if its bit in xstat_bv is
00260      zero.  */
00261   if (clear_bv)
00262     {
00263       if ((clear_bv & I386_XSTATE_X87))
00264         for (i = 0; i < 8; i++)
00265           memset (((char *) &fp->st_space[0]) + i * 16, 0, 10);
00266 
00267       if ((clear_bv & I386_XSTATE_SSE))
00268         for (i = 0; i < num_xmm_registers; i++) 
00269           memset (((char *) &fp->xmm_space[0]) + i * 16, 0, 16);
00270 
00271       if ((clear_bv & I386_XSTATE_AVX))
00272         for (i = 0; i < num_xmm_registers; i++) 
00273           memset (((char *) &fp->ymmh_space[0]) + i * 16, 0, 16);
00274     }
00275 
00276   /* Check if any x87 registers are changed.  */
00277   if ((x86_xcr0 & I386_XSTATE_X87))
00278     {
00279       int st0_regnum = find_regno (regcache->tdesc, "st0");
00280 
00281       for (i = 0; i < 8; i++)
00282         {
00283           collect_register (regcache, i + st0_regnum, raw);
00284           p = ((char *) &fp->st_space[0]) + i * 16;
00285           if (memcmp (raw, p, 10))
00286             {
00287               xstate_bv |= I386_XSTATE_X87;
00288               memcpy (p, raw, 10);
00289             }
00290         }
00291     }
00292 
00293   /* Check if any SSE registers are changed.  */
00294   if ((x86_xcr0 & I386_XSTATE_SSE))
00295     {
00296       int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
00297 
00298       for (i = 0; i < num_xmm_registers; i++) 
00299         {
00300           collect_register (regcache, i + xmm0_regnum, raw);
00301           p = ((char *) &fp->xmm_space[0]) + i * 16;
00302           if (memcmp (raw, p, 16))
00303             {
00304               xstate_bv |= I386_XSTATE_SSE;
00305               memcpy (p, raw, 16);
00306             }
00307         }
00308     }
00309 
00310   /* Check if any AVX registers are changed.  */
00311   if ((x86_xcr0 & I386_XSTATE_AVX))
00312     {
00313       int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h");
00314 
00315       for (i = 0; i < num_xmm_registers; i++) 
00316         {
00317           collect_register (regcache, i + ymm0h_regnum, raw);
00318           p = ((char *) &fp->ymmh_space[0]) + i * 16;
00319           if (memcmp (raw, p, 16))
00320             {
00321               xstate_bv |= I386_XSTATE_AVX;
00322               memcpy (p, raw, 16);
00323             }
00324         }
00325     }
00326 
00327   /* Update the corresponding bits in xstate_bv if any SSE/AVX
00328      registers are changed.  */
00329   fp->xstate_bv |= xstate_bv;
00330 
00331   collect_register_by_name (regcache, "fioff", &fp->fioff);
00332   collect_register_by_name (regcache, "fooff", &fp->fooff);
00333   collect_register_by_name (regcache, "mxcsr", &fp->mxcsr);
00334 
00335   /* This one's 11 bits... */
00336   collect_register_by_name (regcache, "fop", &val2);
00337   fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
00338 
00339   /* Some registers are 16-bit.  */
00340   collect_register_by_name (regcache, "fctrl", &val);
00341   fp->fctrl = val;
00342 
00343   collect_register_by_name (regcache, "fstat", &val);
00344   fp->fstat = val;
00345 
00346   /* Convert to the simplifed tag form stored in fxsave data.  */
00347   collect_register_by_name (regcache, "ftag", &val);
00348   val &= 0xFFFF;
00349   val2 = 0;
00350   for (i = 7; i >= 0; i--)
00351     {
00352       int tag = (val >> (i * 2)) & 3;
00353 
00354       if (tag != 3)
00355         val2 |= (1 << i);
00356     }
00357   fp->ftag = val2;
00358 
00359   collect_register_by_name (regcache, "fiseg", &val);
00360   fp->fiseg = val;
00361 
00362   collect_register_by_name (regcache, "foseg", &val);
00363   fp->foseg = val;
00364 }
00365 
00366 static int
00367 i387_ftag (struct i387_fxsave *fp, int regno)
00368 {
00369   unsigned char *raw = &fp->st_space[regno * 16];
00370   unsigned int exponent;
00371   unsigned long fraction[2];
00372   int integer;
00373 
00374   integer = raw[7] & 0x80;
00375   exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
00376   fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
00377   fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
00378                  | (raw[5] << 8) | raw[4]);
00379 
00380   if (exponent == 0x7fff)
00381     {
00382       /* Special.  */
00383       return (2);
00384     }
00385   else if (exponent == 0x0000)
00386     {
00387       if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
00388         {
00389           /* Zero.  */
00390           return (1);
00391         }
00392       else
00393         {
00394           /* Special.  */
00395           return (2);
00396         }
00397     }
00398   else
00399     {
00400       if (integer)
00401         {
00402           /* Valid.  */
00403           return (0);
00404         }
00405       else
00406         {
00407           /* Special.  */
00408           return (2);
00409         }
00410     }
00411 }
00412 
00413 void
00414 i387_fxsave_to_cache (struct regcache *regcache, const void *buf)
00415 {
00416   struct i387_fxsave *fp = (struct i387_fxsave *) buf;
00417   int i, top;
00418   int st0_regnum = find_regno (regcache->tdesc, "st0");
00419   int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
00420   unsigned long val;
00421   /* Amd64 has 16 xmm regs; I386 has 8 xmm regs.  */
00422   int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
00423 
00424   for (i = 0; i < 8; i++)
00425     supply_register (regcache, i + st0_regnum,
00426                      ((char *) &fp->st_space[0]) + i * 16);
00427   for (i = 0; i < num_xmm_registers; i++)
00428     supply_register (regcache, i + xmm0_regnum,
00429                      ((char *) &fp->xmm_space[0]) + i * 16);
00430 
00431   supply_register_by_name (regcache, "fioff", &fp->fioff);
00432   supply_register_by_name (regcache, "fooff", &fp->fooff);
00433   supply_register_by_name (regcache, "mxcsr", &fp->mxcsr);
00434 
00435   /* Some registers are 16-bit.  */
00436   val = fp->fctrl & 0xFFFF;
00437   supply_register_by_name (regcache, "fctrl", &val);
00438 
00439   val = fp->fstat & 0xFFFF;
00440   supply_register_by_name (regcache, "fstat", &val);
00441 
00442   /* Generate the form of ftag data that GDB expects.  */
00443   top = (fp->fstat >> 11) & 0x7;
00444   val = 0;
00445   for (i = 7; i >= 0; i--)
00446     {
00447       int tag;
00448       if (fp->ftag & (1 << i))
00449         tag = i387_ftag (fp, (i + 8 - top) % 8);
00450       else
00451         tag = 3;
00452       val |= tag << (2 * i);
00453     }
00454   supply_register_by_name (regcache, "ftag", &val);
00455 
00456   val = fp->fiseg & 0xFFFF;
00457   supply_register_by_name (regcache, "fiseg", &val);
00458 
00459   val = fp->foseg & 0xFFFF;
00460   supply_register_by_name (regcache, "foseg", &val);
00461 
00462   val = (fp->fop) & 0x7FF;
00463   supply_register_by_name (regcache, "fop", &val);
00464 }
00465 
00466 void
00467 i387_xsave_to_cache (struct regcache *regcache, const void *buf)
00468 {
00469   struct i387_xsave *fp = (struct i387_xsave *) buf;
00470   struct i387_fxsave *fxp = (struct i387_fxsave *) buf;
00471   int i, top;
00472   unsigned long val;
00473   unsigned int clear_bv;
00474   gdb_byte *p;
00475   /* Amd64 has 16 xmm regs; I386 has 8 xmm regs.  */
00476   int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
00477 
00478   /* The supported bits in `xstat_bv' are 1 byte.  Clear part in
00479      vector registers if its bit in xstat_bv is zero.  */
00480   clear_bv = (~fp->xstate_bv) & x86_xcr0;
00481 
00482   /* Check if any x87 registers are changed.  */
00483   if ((x86_xcr0 & I386_XSTATE_X87) != 0)
00484     {
00485       int st0_regnum = find_regno (regcache->tdesc, "st0");
00486 
00487       if ((clear_bv & I386_XSTATE_X87) != 0)
00488         {
00489           for (i = 0; i < 8; i++)
00490             supply_register_zeroed (regcache, i + st0_regnum);
00491         }
00492       else
00493         {
00494           p = (gdb_byte *) &fp->st_space[0];
00495           for (i = 0; i < 8; i++)
00496             supply_register (regcache, i + st0_regnum, p + i * 16);
00497         }
00498     }
00499 
00500   if ((x86_xcr0 & I386_XSTATE_SSE) != 0)
00501     {
00502       int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
00503 
00504       if ((clear_bv & I386_XSTATE_SSE))
00505         {
00506           for (i = 0; i < num_xmm_registers; i++)
00507             supply_register_zeroed (regcache, i + xmm0_regnum);
00508         }
00509       else
00510         {
00511           p = (gdb_byte *) &fp->xmm_space[0];
00512           for (i = 0; i < num_xmm_registers; i++)
00513             supply_register (regcache, i + xmm0_regnum, p + i * 16);
00514         }
00515     }
00516 
00517   if ((x86_xcr0 & I386_XSTATE_AVX) != 0)
00518     {
00519       int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h");
00520 
00521       if ((clear_bv & I386_XSTATE_AVX) != 0)
00522         {
00523           for (i = 0; i < num_xmm_registers; i++)
00524             supply_register_zeroed (regcache, i + ymm0h_regnum);
00525         }
00526       else
00527         {
00528           p = (gdb_byte *) &fp->ymmh_space[0];
00529           for (i = 0; i < num_xmm_registers; i++)
00530             supply_register (regcache, i + ymm0h_regnum, p + i * 16);
00531         }
00532     }
00533 
00534   supply_register_by_name (regcache, "fioff", &fp->fioff);
00535   supply_register_by_name (regcache, "fooff", &fp->fooff);
00536   supply_register_by_name (regcache, "mxcsr", &fp->mxcsr);
00537 
00538   /* Some registers are 16-bit.  */
00539   val = fp->fctrl & 0xFFFF;
00540   supply_register_by_name (regcache, "fctrl", &val);
00541 
00542   val = fp->fstat & 0xFFFF;
00543   supply_register_by_name (regcache, "fstat", &val);
00544 
00545   /* Generate the form of ftag data that GDB expects.  */
00546   top = (fp->fstat >> 11) & 0x7;
00547   val = 0;
00548   for (i = 7; i >= 0; i--)
00549     {
00550       int tag;
00551       if (fp->ftag & (1 << i))
00552         tag = i387_ftag (fxp, (i + 8 - top) % 8);
00553       else
00554         tag = 3;
00555       val |= tag << (2 * i);
00556     }
00557   supply_register_by_name (regcache, "ftag", &val);
00558 
00559   val = fp->fiseg & 0xFFFF;
00560   supply_register_by_name (regcache, "fiseg", &val);
00561 
00562   val = fp->foseg & 0xFFFF;
00563   supply_register_by_name (regcache, "foseg", &val);
00564 
00565   val = (fp->fop) & 0x7FF;
00566   supply_register_by_name (regcache, "fop", &val);
00567 }
00568 
00569 /* Default to SSE.  */
00570 unsigned long long x86_xcr0 = I386_XSTATE_SSE_MASK;
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines