Fix date of last commit.
[external/binutils.git] / gdb / i387-nat.c
1 /* Native-dependent code for the i387.
2    Copyright 2000 Free Software Foundation, Inc.
3
4    This file is part of GDB.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include "defs.h"
22 #include "inferior.h"
23 #include "value.h"
24
25 /* FIXME: kettenis/2000-05-21: Right now more than a few i386 targets
26    define their own routines to manage the floating-point registers in
27    GDB's register array.  Most (if not all) of these targets use the
28    format used by the "fsave" instruction in their communication with
29    the OS.  They should all be converted to use the routines below.  */
30
31 /* At fsave_offset[REGNO] you'll find the offset to the location in
32    the data structure used by the "fsave" instruction where GDB
33    register REGNO is stored.  */
34
35 static int fsave_offset[] =
36 {
37   28 + 0 * FPU_REG_RAW_SIZE,    /* FP0_REGNUM through ...  */
38   28 + 1 * FPU_REG_RAW_SIZE,  
39   28 + 2 * FPU_REG_RAW_SIZE,  
40   28 + 3 * FPU_REG_RAW_SIZE,  
41   28 + 4 * FPU_REG_RAW_SIZE,  
42   28 + 5 * FPU_REG_RAW_SIZE,  
43   28 + 6 * FPU_REG_RAW_SIZE,  
44   28 + 7 * FPU_REG_RAW_SIZE,    /* ... FP7_REGNUM.  */
45   0,                            /* FCTRL_REGNUM (16 bits).  */
46   4,                            /* FSTAT_REGNUM (16 bits).  */
47   8,                            /* FTAG_REGNUM (16 bits).  */
48   16,                           /* FCS_REGNUM (16 bits).  */
49   12,                           /* FCOFF_REGNUM.  */
50   24,                           /* FDS_REGNUM.  */
51   20,                           /* FDOFF_REGNUM.  */
52   18                            /* FOP_REGNUM (bottom 11 bits).  */
53 };
54
55 #define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
56 \f
57
58 /* Fill GDB's register array with the floating-point register values
59    in *FSAVE.  This function masks off any of the reserved
60    bits in *FSAVE.  */
61
62 void
63 i387_supply_fsave (char *fsave)
64 {
65   int i;
66
67   for (i = FP0_REGNUM; i <= LAST_FPU_CTRL_REGNUM; i++)
68     {
69       /* Most of the FPU control registers occupy only 16 bits in
70          the fsave area.  Give those a special treatment.  */
71       if (i >= FIRST_FPU_CTRL_REGNUM
72           && i != FCOFF_REGNUM && i != FDOFF_REGNUM)
73         {
74           unsigned int val = *(unsigned short *) (FSAVE_ADDR (fsave, i));
75
76           if (i == FOP_REGNUM)
77             {
78               val &= ((1 << 11) - 1);
79               supply_register (i, (char *) &val);
80             }
81           else
82             supply_register (i, (char *) &val);
83         }
84       else
85         supply_register (i, FSAVE_ADDR (fsave, i));
86     }
87 }
88
89 /* Fill register REGNO (if it is a floating-point register) in *FSAVE
90    with the value in GDB's register array.  If REGNO is -1, do this
91    for all registers.  This function doesn't touch any of the reserved
92    bits in *FSAVE.  */
93
94 void
95 i387_fill_fsave (char *fsave, int regno)
96 {
97   int i;
98
99   for (i = FP0_REGNUM; i <= LAST_FPU_CTRL_REGNUM; i++)
100     if (regno == -1 || regno == i)
101       {
102         /* Most of the FPU control registers occupy only 16 bits in
103            the fsave area.  Give those a special treatment.  */
104         if (i >= FIRST_FPU_CTRL_REGNUM
105             && i != FCOFF_REGNUM && i != FDOFF_REGNUM)
106           {
107             if (i == FOP_REGNUM)
108               {
109                 unsigned short oldval, newval;
110
111                 /* The opcode occupies only 11 bits.  */
112                 oldval = (*(unsigned short *) (FSAVE_ADDR (fsave, i)));
113                 newval = *(unsigned short *) &registers[REGISTER_BYTE (i)];
114                 newval &= ((1 << 11) - 1);
115                 newval |= oldval & ~((1 << 11) - 1);
116                 memcpy (FSAVE_ADDR (fsave, i), &newval, 2);
117               }
118             else
119               memcpy (FSAVE_ADDR (fsave, i), &registers[REGISTER_BYTE (i)], 2);
120           }
121         else
122           memcpy (FSAVE_ADDR (fsave, i), &registers[REGISTER_BYTE (i)],
123                   REGISTER_RAW_SIZE (i));
124       }
125 }
126 \f
127
128 /* At fxsave_offset[REGNO] you'll find the offset to the location in
129    the data structure used by the "fxsave" instruction where GDB
130    register REGNO is stored.  */
131
132 static int fxsave_offset[] =
133 {
134   32,                           /* FP0_REGNUM through ...  */
135   48,
136   64,
137   80,
138   96,
139   112,
140   128,
141   144,                          /* ... FP7_REGNUM (80 bits each).  */
142   0,                            /* FCTRL_REGNUM (16 bits).  */
143   2,                            /* FSTAT_REGNUM (16 bits).  */
144   4,                            /* FTAG_REGNUM (16 bits).  */
145   12,                           /* FCS_REGNUM (16 bits).  */
146   8,                            /* FCOFF_REGNUM.  */
147   20,                           /* FDS_REGNUM (16 bits).  */
148   16,                           /* FDOFF_REGNUM.  */
149   6,                            /* FOP_REGNUM (bottom 11 bits).  */
150   160,                          /* XMM0_REGNUM through ...  */
151   176,
152   192,
153   208,
154   224,
155   240,
156   256,
157   272,                          /* ... XMM7_REGNUM (128 bits each).  */
158   24,                           /* MXCSR_REGNUM.  */
159 };
160
161 #define FXSAVE_ADDR(fxsave, regnum) \
162   (fxsave + fxsave_offset[regnum - FP0_REGNUM])
163
164 static int i387_tag (unsigned char *raw);
165 \f
166
167 /* Fill GDB's register array with the floating-point and SSE register
168    values in *FXSAVE.  This function masks off any of the reserved
169    bits in *FXSAVE.  */
170
171 void
172 i387_supply_fxsave (char *fxsave)
173 {
174   int i;
175
176   for (i = FP0_REGNUM; i <= MXCSR_REGNUM; i++)
177     {
178       /* Most of the FPU control registers occupy only 16 bits in
179          the fxsave area.  Give those a special treatment.  */
180       if (i >= FIRST_FPU_CTRL_REGNUM && i < XMM0_REGNUM
181           && i != FCOFF_REGNUM && i != FDOFF_REGNUM)
182         {
183           unsigned long val = *(unsigned short *) (FXSAVE_ADDR (fxsave, i));
184
185           if (i == FOP_REGNUM)
186             {
187               val &= ((1 << 11) - 1);
188               supply_register (i, (char *) &val);
189             }
190           else if (i== FTAG_REGNUM)
191             {
192               /* The fxsave area contains a simplified version of the
193                  tag word.  We have to look at the actual 80-bit FP
194                  data to recreate the traditional i387 tag word.  */
195
196               unsigned long ftag = 0;
197               unsigned long fstat;
198               int fpreg;
199               int top;
200
201               fstat = *(unsigned short *) (FXSAVE_ADDR (fxsave, FSTAT_REGNUM));
202               top = ((fstat >> 11) & 0x111);
203
204               for (fpreg = 7; fpreg >= 0; fpreg--)
205                 {
206                   int tag = 0x11;
207
208                   if (val & (1 << fpreg))
209                     {
210                       int regnum = (fpreg + 8 - top) % 8 + FP0_REGNUM;
211                       tag = i387_tag (FXSAVE_ADDR (fxsave, regnum));
212                     }
213
214                   ftag |= tag << (2 * fpreg);
215                 }
216               supply_register (i, (char *) &ftag);
217             }
218           else
219             supply_register (i, (char *) &val);
220         }
221       else
222         supply_register (i, FXSAVE_ADDR (fxsave, i));
223     }
224 }
225
226 /* Fill register REGNO (if it is a floating-point or SSE register) in
227    *FXSAVE with the value in GDB's register array.  If REGNO is -1, do
228    this for all registers.  This function doesn't touch any of the
229    reserved bits in *FXSAVE.  */
230
231 void
232 i387_fill_fxsave (char *fxsave, int regno)
233 {
234   int i;
235
236   for (i = FP0_REGNUM; i <= MXCSR_REGNUM; i++)
237     if (regno == -1 || regno == i)
238       {
239         /* Most of the FPU control registers occupy only 16 bits in
240            the fxsave area.  Give those a special treatment.  */
241         if (i >= FIRST_FPU_CTRL_REGNUM && i < XMM0_REGNUM
242             && i != FCOFF_REGNUM && i != FDOFF_REGNUM)
243           {
244             if (i == FOP_REGNUM)
245               {
246                 unsigned short oldval, newval;
247
248                 /* The opcode occupies only 11 bits.  */
249                 oldval = (*(unsigned short *) (FXSAVE_ADDR (fxsave, i)));
250                 newval = *(unsigned short *) &registers[REGISTER_BYTE (i)];
251                 newval &= ((1 << 11) - 1);
252                 newval |= oldval & ~((1 << 11) - 1);
253                 memcpy (FXSAVE_ADDR (fxsave, i), &newval, 2);
254               }
255             else if (i == FTAG_REGNUM)
256               {
257                 /* Converting back is much easier.  */
258
259                 unsigned char val = 0;
260                 unsigned short ftag;
261                 int fpreg;
262
263                 ftag = *(unsigned short *) &registers[REGISTER_BYTE (i)];
264
265                 for (fpreg = 7; fpreg >= 0; fpreg--)
266                   {
267                     int tag = (ftag >> (fpreg * 2)) & 0x11;
268
269                     if (tag != 0x11)
270                       val |= (1 << fpreg);
271                   }
272
273                 memcpy (FXSAVE_ADDR (fxsave, i), &val, 2);
274               }
275             else
276               memcpy (FXSAVE_ADDR (fxsave, i),
277                       &registers[REGISTER_BYTE (i)], 2);
278           }
279         else
280           memcpy (FXSAVE_ADDR (fxsave, i), &registers[REGISTER_BYTE (i)],
281                   REGISTER_RAW_SIZE (i));
282       }
283 }
284
285 /* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
286    *RAW.  */
287
288 static int
289 i387_tag (unsigned char *raw)
290 {
291   int integer;
292   unsigned int exponent;
293   unsigned long fraction[2];
294
295   integer = raw[7] & 0x80;
296   exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
297   fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
298   fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
299                  | (raw[5] << 8) | raw[4]);
300
301   if (exponent == 0x7fff)
302     {
303       /* Special.  */
304       return (0x10);
305     }
306   else if (exponent == 0x0000)
307     {
308       if (integer)
309         {
310           /* Valid.  */
311           return (0x00);
312         }
313       else
314         {
315           /* Special.  */
316           return (0x10);
317         }
318     }
319   else
320     {
321       if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
322         {
323           /* Zero.  */
324           return (0x01);
325         }
326       else
327         {
328           /* Special.  */
329           return (0x10);
330         }
331     }
332 }