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