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