]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/i387-nat.c
7cb42baa99bf1566ccbdedfb876e050758ad5d04
1 /* Native-dependent code for the i387.
2 Copyright 2000, 2001, 2002 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. */
27 #include "i386-tdep.h"
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. */
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. */
39 static int fsave_offset
[] =
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). */
59 #define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
62 /* Fill register REGNUM in GDB's register array with the appropriate
63 value from *FSAVE. This function masks off any of the reserved
67 i387_supply_register (int regnum
, char *fsave
)
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
)
76 memcpy (val
, FSAVE_ADDR (fsave
, regnum
), 2);
78 if (regnum
== FOP_REGNUM
)
79 val
[1] &= ((1 << 3) - 1);
80 supply_register (regnum
, val
);
83 supply_register (regnum
, FSAVE_ADDR (fsave
, regnum
));
86 /* Fill GDB's register array with the floating-point register values
87 in *FSAVE. This function masks off any of the reserved
91 i387_supply_fsave (char *fsave
)
95 for (i
= FP0_REGNUM
; i
< XMM0_REGNUM
; i
++)
96 i387_supply_register (i
, fsave
);
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
105 i387_fill_fsave (char *fsave
, int regnum
)
109 for (i
= FP0_REGNUM
; i
< XMM0_REGNUM
; i
++)
110 if (regnum
== -1 || regnum
== i
)
112 /* Most of the FPU control registers occupy only 16 bits in
113 the fsave area. Give those a special treatment. */
115 && i
!= FIOFF_REGNUM
&& i
!= FOOFF_REGNUM
)
117 unsigned char buf
[4];
119 regcache_collect (i
, buf
);
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));
128 memcpy (FSAVE_ADDR (fsave
, i
), buf
, 2);
131 regcache_collect (i
, FSAVE_ADDR (fsave
, i
));
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. */
140 static int fxsave_offset
[] =
142 32, /* FP0_REGNUM through ... */
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 ... */
165 272, /* ... XMM7_REGNUM (128 bits each). */
166 24, /* MXCSR_REGNUM. */
169 #define FXSAVE_ADDR(fxsave, regnum) \
170 (fxsave + fxsave_offset[regnum - FP0_REGNUM])
172 static int i387_tag (unsigned char *raw
);
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
180 i387_supply_fxsave (char *fxsave
)
184 for (i
= FP0_REGNUM
; i
<= MXCSR_REGNUM
; i
++)
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
)
191 unsigned char val
[4];
193 memcpy (val
, FXSAVE_ADDR (fxsave
, i
), 2);
196 val
[1] &= ((1 << 3) - 1);
197 else if (i
== FTAG_REGNUM
)
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. */
203 unsigned long ftag
= 0;
207 top
= (((FXSAVE_ADDR (fxsave
, FSTAT_REGNUM
))[1] >> 3) & 0x7);
209 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
213 if (val
[0] & (1 << fpreg
))
215 int regnum
= (fpreg
+ 8 - top
) % 8 + FP0_REGNUM
;
216 tag
= i387_tag (FXSAVE_ADDR (fxsave
, regnum
));
221 ftag
|= tag
<< (2 * fpreg
);
223 val
[0] = ftag
& 0xff;
224 val
[1] = (ftag
>> 8) & 0xff;
226 supply_register (i
, val
);
229 supply_register (i
, FXSAVE_ADDR (fxsave
, i
));
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. */
239 i387_fill_fxsave (char *fxsave
, int regnum
)
243 for (i
= FP0_REGNUM
; i
<= MXCSR_REGNUM
; i
++)
244 if (regnum
== -1 || regnum
== i
)
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
)
251 unsigned char buf
[4];
253 regcache_collect (i
, buf
);
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));
262 else if (i
== FTAG_REGNUM
)
264 /* Converting back is much easier. */
269 ftag
= (buf
[1] << 8) | buf
[0];
273 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
275 int tag
= (ftag
>> (fpreg
* 2)) & 3;
278 buf
[0] |= (1 << fpreg
);
281 memcpy (FXSAVE_ADDR (fxsave
, i
), buf
, 2);
284 regcache_collect (i
, FXSAVE_ADDR (fxsave
, i
));
288 /* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
292 i387_tag (unsigned char *raw
)
295 unsigned int exponent
;
296 unsigned long fraction
[2];
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]);
304 if (exponent
== 0x7fff)
309 else if (exponent
== 0x0000)
311 if (fraction
[0] == 0x0000 && fraction
[1] == 0x0000 && !integer
)