Commit | Line | Data |
---|---|---|
b2450fc5 MK |
1 | /* Native-dependent code for the i387. |
2 | Copyright (C) 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 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 *) ®isters[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), ®isters[REGISTER_BYTE (i)], 2); | |
120 | } | |
121 | else | |
122 | memcpy (FSAVE_ADDR (fsave, i), ®isters[REGISTER_BYTE (i)], | |
123 | REGISTER_RAW_SIZE (i)); | |
124 | } | |
125 | } |