1 /* Native-dependent code for the i387.
2 Copyright 2000, 2001 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
28 /* FIXME: kettenis/2000-05-21: Right now more than a few i386 targets
29 define their own routines to manage the floating-point registers in
30 GDB's register array. Most (if not all) of these targets use the
31 format used by the "fsave" instruction in their communication with
32 the OS. They should all be converted to use the routines below. */
34 /* At fsave_offset[REGNUM] you'll find the offset to the location in
35 the data structure used by the "fsave" instruction where GDB
36 register REGNUM is stored. */
38 static int fsave_offset
[] =
40 28 + 0 * FPU_REG_RAW_SIZE
, /* FP0_REGNUM through ... */
41 28 + 1 * FPU_REG_RAW_SIZE
,
42 28 + 2 * FPU_REG_RAW_SIZE
,
43 28 + 3 * FPU_REG_RAW_SIZE
,
44 28 + 4 * FPU_REG_RAW_SIZE
,
45 28 + 5 * FPU_REG_RAW_SIZE
,
46 28 + 6 * FPU_REG_RAW_SIZE
,
47 28 + 7 * FPU_REG_RAW_SIZE
, /* ... FP7_REGNUM. */
48 0, /* FCTRL_REGNUM (16 bits). */
49 4, /* FSTAT_REGNUM (16 bits). */
50 8, /* FTAG_REGNUM (16 bits). */
51 16, /* FCS_REGNUM (16 bits). */
52 12, /* FCOFF_REGNUM. */
54 20, /* FDOFF_REGNUM. */
55 18 /* FOP_REGNUM (bottom 11 bits). */
58 #define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
61 /* Fill register REGNUM in GDB's register array with the appropriate
62 value from *FSAVE. This function masks off any of the reserved
66 i387_supply_register (int regnum
, char *fsave
)
68 /* Most of the FPU control registers occupy only 16 bits in
69 the fsave area. Give those a special treatment. */
70 if (regnum
>= FIRST_FPU_CTRL_REGNUM
71 && regnum
!= FCOFF_REGNUM
&& regnum
!= FDOFF_REGNUM
)
73 unsigned int val
= *(unsigned short *) (FSAVE_ADDR (fsave
, regnum
));
75 if (regnum
== FOP_REGNUM
)
77 val
&= ((1 << 11) - 1);
78 supply_register (regnum
, (char *) &val
);
81 supply_register (regnum
, (char *) &val
);
84 supply_register (regnum
, FSAVE_ADDR (fsave
, regnum
));
87 /* Fill GDB's register array with the floating-point register values
88 in *FSAVE. This function masks off any of the reserved
92 i387_supply_fsave (char *fsave
)
96 for (i
= FP0_REGNUM
; i
<= LAST_FPU_CTRL_REGNUM
; i
++)
97 i387_supply_register (i
, fsave
);
100 /* Fill register REGNUM (if it is a floating-point register) in *FSAVE
101 with the value in GDB's register array. If REGNUM is -1, do this
102 for all registers. This function doesn't touch any of the reserved
106 i387_fill_fsave (char *fsave
, int regnum
)
110 for (i
= FP0_REGNUM
; i
<= LAST_FPU_CTRL_REGNUM
; i
++)
111 if (regnum
== -1 || regnum
== i
)
113 /* Most of the FPU control registers occupy only 16 bits in
114 the fsave area. Give those a special treatment. */
115 if (i
>= FIRST_FPU_CTRL_REGNUM
116 && i
!= FCOFF_REGNUM
&& i
!= FDOFF_REGNUM
)
120 unsigned short oldval
, newval
;
122 /* The opcode occupies only 11 bits. */
123 oldval
= (*(unsigned short *) (FSAVE_ADDR (fsave
, i
)));
124 newval
= *(unsigned short *) ®isters
[REGISTER_BYTE (i
)];
125 newval
&= ((1 << 11) - 1);
126 newval
|= oldval
& ~((1 << 11) - 1);
127 memcpy (FSAVE_ADDR (fsave
, i
), &newval
, 2);
130 memcpy (FSAVE_ADDR (fsave
, i
), ®isters
[REGISTER_BYTE (i
)], 2);
133 memcpy (FSAVE_ADDR (fsave
, i
), ®isters
[REGISTER_BYTE (i
)],
134 REGISTER_RAW_SIZE (i
));
139 /* At fxsave_offset[REGNUM] you'll find the offset to the location in
140 the data structure used by the "fxsave" instruction where GDB
141 register REGNUM is stored. */
143 static int fxsave_offset
[] =
145 32, /* FP0_REGNUM through ... */
152 144, /* ... FP7_REGNUM (80 bits each). */
153 0, /* FCTRL_REGNUM (16 bits). */
154 2, /* FSTAT_REGNUM (16 bits). */
155 4, /* FTAG_REGNUM (16 bits). */
156 12, /* FCS_REGNUM (16 bits). */
157 8, /* FCOFF_REGNUM. */
158 20, /* FDS_REGNUM (16 bits). */
159 16, /* FDOFF_REGNUM. */
160 6, /* FOP_REGNUM (bottom 11 bits). */
161 160, /* XMM0_REGNUM through ... */
168 272, /* ... XMM7_REGNUM (128 bits each). */
169 24, /* MXCSR_REGNUM. */
172 #define FXSAVE_ADDR(fxsave, regnum) \
173 (fxsave + fxsave_offset[regnum - FP0_REGNUM])
175 static int i387_tag (unsigned char *raw
);
178 /* Fill GDB's register array with the floating-point and SSE register
179 values in *FXSAVE. This function masks off any of the reserved
183 i387_supply_fxsave (char *fxsave
)
187 for (i
= FP0_REGNUM
; i
<= MXCSR_REGNUM
; i
++)
189 /* Most of the FPU control registers occupy only 16 bits in
190 the fxsave area. Give those a special treatment. */
191 if (i
>= FIRST_FPU_CTRL_REGNUM
&& i
< XMM0_REGNUM
192 && i
!= FCOFF_REGNUM
&& i
!= FDOFF_REGNUM
)
194 unsigned long val
= *(unsigned short *) (FXSAVE_ADDR (fxsave
, i
));
198 val
&= ((1 << 11) - 1);
199 supply_register (i
, (char *) &val
);
201 else if (i
== FTAG_REGNUM
)
203 /* The fxsave area contains a simplified version of the
204 tag word. We have to look at the actual 80-bit FP
205 data to recreate the traditional i387 tag word. */
207 unsigned long ftag
= 0;
212 fstat
= *(unsigned short *) (FXSAVE_ADDR (fxsave
, FSTAT_REGNUM
));
213 top
= ((fstat
>> 11) & 0x7);
215 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
219 if (val
& (1 << fpreg
))
221 int regnum
= (fpreg
+ 8 - top
) % 8 + FP0_REGNUM
;
222 tag
= i387_tag (FXSAVE_ADDR (fxsave
, regnum
));
227 ftag
|= tag
<< (2 * fpreg
);
229 supply_register (i
, (char *) &ftag
);
232 supply_register (i
, (char *) &val
);
235 supply_register (i
, FXSAVE_ADDR (fxsave
, i
));
239 /* Fill register REGNUM (if it is a floating-point or SSE register) in
240 *FXSAVE with the value in GDB's register array. If REGNUM is -1, do
241 this for all registers. This function doesn't touch any of the
242 reserved bits in *FXSAVE. */
245 i387_fill_fxsave (char *fxsave
, int regnum
)
249 for (i
= FP0_REGNUM
; i
<= MXCSR_REGNUM
; i
++)
250 if (regnum
== -1 || regnum
== i
)
252 /* Most of the FPU control registers occupy only 16 bits in
253 the fxsave area. Give those a special treatment. */
254 if (i
>= FIRST_FPU_CTRL_REGNUM
&& i
< XMM0_REGNUM
255 && i
!= FCOFF_REGNUM
&& i
!= FDOFF_REGNUM
)
259 unsigned short oldval
, newval
;
261 /* The opcode occupies only 11 bits. */
262 oldval
= (*(unsigned short *) (FXSAVE_ADDR (fxsave
, i
)));
263 newval
= *(unsigned short *) ®isters
[REGISTER_BYTE (i
)];
264 newval
&= ((1 << 11) - 1);
265 newval
|= oldval
& ~((1 << 11) - 1);
266 memcpy (FXSAVE_ADDR (fxsave
, i
), &newval
, 2);
268 else if (i
== FTAG_REGNUM
)
270 /* Converting back is much easier. */
272 unsigned char val
= 0;
276 ftag
= *(unsigned short *) ®isters
[REGISTER_BYTE (i
)];
278 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
280 int tag
= (ftag
>> (fpreg
* 2)) & 3;
283 val
|= (1 << (fpreg
* 2));
286 memcpy (FXSAVE_ADDR (fxsave
, i
), &val
, 2);
289 memcpy (FXSAVE_ADDR (fxsave
, i
),
290 ®isters
[REGISTER_BYTE (i
)], 2);
293 memcpy (FXSAVE_ADDR (fxsave
, i
), ®isters
[REGISTER_BYTE (i
)],
294 REGISTER_RAW_SIZE (i
));
298 /* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
302 i387_tag (unsigned char *raw
)
305 unsigned int exponent
;
306 unsigned long fraction
[2];
308 integer
= raw
[7] & 0x80;
309 exponent
= (((raw
[9] & 0x7f) << 8) | raw
[8]);
310 fraction
[0] = ((raw
[3] << 24) | (raw
[2] << 16) | (raw
[1] << 8) | raw
[0]);
311 fraction
[1] = (((raw
[7] & 0x7f) << 24) | (raw
[6] << 16)
312 | (raw
[5] << 8) | raw
[4]);
314 if (exponent
== 0x7fff)
319 else if (exponent
== 0x0000)
321 if (fraction
[0] == 0x0000 && fraction
[1] == 0x0000 && !integer
)
This page took 0.040971 seconds and 4 git commands to generate.