gdb/testsuite/
[deliverable/binutils-gdb.git] / gdb / gdbserver / i387-fp.c
CommitLineData
58caa3dc 1/* i387-specific utility functions, for the remote server for GDB.
4c38e0a4 2 Copyright (C) 2000, 2001, 2002, 2005, 2007, 2008, 2009, 2010
9b254dd1 3 Free Software Foundation, Inc.
58caa3dc
DJ
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
58caa3dc
DJ
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
58caa3dc
DJ
19
20#include "server.h"
0d62e5e8 21#include "i387-fp.h"
58caa3dc
DJ
22
23int num_xmm_registers = 8;
24
25/* Note: These functions preserve the reserved bits in control registers.
26 However, gdbserver promptly throws away that information. */
27
28/* These structs should have the proper sizes and alignment on both
29 i386 and x86-64 machines. */
30
31struct i387_fsave {
32 /* All these are only sixteen bits, plus padding, except for fop (which
33 is only eleven bits), and fooff / fioff (which are 32 bits each). */
0c2ead7e
DJ
34 unsigned short fctrl;
35 unsigned short pad1;
36 unsigned short fstat;
37 unsigned short pad2;
38 unsigned short ftag;
39 unsigned short pad3;
58caa3dc
DJ
40 unsigned int fioff;
41 unsigned short fiseg;
42 unsigned short fop;
43 unsigned int fooff;
0c2ead7e
DJ
44 unsigned short foseg;
45 unsigned short pad4;
58caa3dc
DJ
46
47 /* Space for eight 80-bit FP values. */
f450004a 48 unsigned char st_space[80];
58caa3dc
DJ
49};
50
51struct i387_fxsave {
52 /* All these are only sixteen bits, plus padding, except for fop (which
53 is only eleven bits), and fooff / fioff (which are 32 bits each). */
54 unsigned short fctrl;
55 unsigned short fstat;
56 unsigned short ftag;
57 unsigned short fop;
58 unsigned int fioff;
0c2ead7e
DJ
59 unsigned short fiseg;
60 unsigned short pad1;
58caa3dc 61 unsigned int fooff;
0c2ead7e
DJ
62 unsigned short foseg;
63 unsigned short pad12;
58caa3dc
DJ
64
65 unsigned int mxcsr;
0c2ead7e 66 unsigned int pad3;
58caa3dc
DJ
67
68 /* Space for eight 80-bit FP values in 128-bit spaces. */
f450004a 69 unsigned char st_space[128];
58caa3dc
DJ
70
71 /* Space for eight 128-bit XMM values, or 16 on x86-64. */
f450004a 72 unsigned char xmm_space[256];
58caa3dc
DJ
73};
74
75void
76i387_cache_to_fsave (void *buf)
77{
78 struct i387_fsave *fp = (struct i387_fsave *) buf;
79 int i;
80 int st0_regnum = find_regno ("st0");
81 unsigned long val, val2;
82
83 for (i = 0; i < 8; i++)
84 collect_register (i + st0_regnum, ((char *) &fp->st_space[0]) + i * 10);
85
86 collect_register_by_name ("fioff", &fp->fioff);
87 collect_register_by_name ("fooff", &fp->fooff);
88
89 /* This one's 11 bits... */
90 collect_register_by_name ("fop", &val2);
91 fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
92
93 /* Some registers are 16-bit. */
94 collect_register_by_name ("fctrl", &val);
0c2ead7e 95 fp->fctrl = val;
58caa3dc
DJ
96
97 collect_register_by_name ("fstat", &val);
98 val &= 0xFFFF;
0c2ead7e 99 fp->fstat = val;
58caa3dc
DJ
100
101 collect_register_by_name ("ftag", &val);
102 val &= 0xFFFF;
0c2ead7e 103 fp->ftag = val;
58caa3dc
DJ
104
105 collect_register_by_name ("fiseg", &val);
106 val &= 0xFFFF;
0c2ead7e 107 fp->fiseg = val;
58caa3dc
DJ
108
109 collect_register_by_name ("foseg", &val);
110 val &= 0xFFFF;
0c2ead7e 111 fp->foseg = val;
58caa3dc
DJ
112}
113
114void
0d62e5e8 115i387_fsave_to_cache (const void *buf)
58caa3dc
DJ
116{
117 struct i387_fsave *fp = (struct i387_fsave *) buf;
118 int i;
119 int st0_regnum = find_regno ("st0");
120 unsigned long val;
121
122 for (i = 0; i < 8; i++)
123 supply_register (i + st0_regnum, ((char *) &fp->st_space[0]) + i * 10);
124
125 supply_register_by_name ("fioff", &fp->fioff);
126 supply_register_by_name ("fooff", &fp->fooff);
1b3f6016 127
58caa3dc
DJ
128 /* Some registers are 16-bit. */
129 val = fp->fctrl & 0xFFFF;
130 supply_register_by_name ("fctrl", &val);
131
132 val = fp->fstat & 0xFFFF;
133 supply_register_by_name ("fstat", &val);
134
135 val = fp->ftag & 0xFFFF;
136 supply_register_by_name ("ftag", &val);
137
138 val = fp->fiseg & 0xFFFF;
139 supply_register_by_name ("fiseg", &val);
140
141 val = fp->foseg & 0xFFFF;
142 supply_register_by_name ("foseg", &val);
143
0c2ead7e 144 /* fop has only 11 valid bits. */
58caa3dc
DJ
145 val = (fp->fop) & 0x7FF;
146 supply_register_by_name ("fop", &val);
147}
148
149void
150i387_cache_to_fxsave (void *buf)
151{
152 struct i387_fxsave *fp = (struct i387_fxsave *) buf;
153 int i;
154 int st0_regnum = find_regno ("st0");
155 int xmm0_regnum = find_regno ("xmm0");
156 unsigned long val, val2;
157
158 for (i = 0; i < 8; i++)
159 collect_register (i + st0_regnum, ((char *) &fp->st_space[0]) + i * 16);
160 for (i = 0; i < num_xmm_registers; i++)
161 collect_register (i + xmm0_regnum, ((char *) &fp->xmm_space[0]) + i * 16);
162
163 collect_register_by_name ("fioff", &fp->fioff);
164 collect_register_by_name ("fooff", &fp->fooff);
165 collect_register_by_name ("mxcsr", &fp->mxcsr);
1b3f6016 166
58caa3dc
DJ
167 /* This one's 11 bits... */
168 collect_register_by_name ("fop", &val2);
169 fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
170
171 /* Some registers are 16-bit. */
172 collect_register_by_name ("fctrl", &val);
0c2ead7e 173 fp->fctrl = val;
58caa3dc
DJ
174
175 collect_register_by_name ("fstat", &val);
0c2ead7e 176 fp->fstat = val;
58caa3dc
DJ
177
178 /* Convert to the simplifed tag form stored in fxsave data. */
179 collect_register_by_name ("ftag", &val);
180 val &= 0xFFFF;
73725ff3 181 val2 = 0;
58caa3dc
DJ
182 for (i = 7; i >= 0; i--)
183 {
184 int tag = (val >> (i * 2)) & 3;
185
186 if (tag != 3)
187 val2 |= (1 << i);
188 }
0c2ead7e 189 fp->ftag = val2;
58caa3dc
DJ
190
191 collect_register_by_name ("fiseg", &val);
0c2ead7e 192 fp->fiseg = val;
58caa3dc
DJ
193
194 collect_register_by_name ("foseg", &val);
0c2ead7e 195 fp->foseg = val;
58caa3dc
DJ
196}
197
198static int
199i387_ftag (struct i387_fxsave *fp, int regno)
200{
201 unsigned char *raw = &fp->st_space[regno * 16];
202 unsigned int exponent;
203 unsigned long fraction[2];
204 int integer;
205
206 integer = raw[7] & 0x80;
207 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
208 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
209 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
1b3f6016 210 | (raw[5] << 8) | raw[4]);
58caa3dc
DJ
211
212 if (exponent == 0x7fff)
213 {
214 /* Special. */
215 return (2);
216 }
217 else if (exponent == 0x0000)
218 {
219 if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
1b3f6016
PA
220 {
221 /* Zero. */
222 return (1);
223 }
58caa3dc 224 else
1b3f6016
PA
225 {
226 /* Special. */
227 return (2);
228 }
58caa3dc
DJ
229 }
230 else
231 {
232 if (integer)
1b3f6016
PA
233 {
234 /* Valid. */
235 return (0);
236 }
58caa3dc 237 else
1b3f6016
PA
238 {
239 /* Special. */
240 return (2);
241 }
58caa3dc
DJ
242 }
243}
244
245void
0d62e5e8 246i387_fxsave_to_cache (const void *buf)
58caa3dc
DJ
247{
248 struct i387_fxsave *fp = (struct i387_fxsave *) buf;
249 int i, top;
250 int st0_regnum = find_regno ("st0");
251 int xmm0_regnum = find_regno ("xmm0");
252 unsigned long val;
253
254 for (i = 0; i < 8; i++)
255 supply_register (i + st0_regnum, ((char *) &fp->st_space[0]) + i * 16);
256 for (i = 0; i < num_xmm_registers; i++)
257 supply_register (i + xmm0_regnum, ((char *) &fp->xmm_space[0]) + i * 16);
258
259 supply_register_by_name ("fioff", &fp->fioff);
260 supply_register_by_name ("fooff", &fp->fooff);
261 supply_register_by_name ("mxcsr", &fp->mxcsr);
1b3f6016 262
58caa3dc
DJ
263 /* Some registers are 16-bit. */
264 val = fp->fctrl & 0xFFFF;
265 supply_register_by_name ("fctrl", &val);
266
267 val = fp->fstat & 0xFFFF;
268 supply_register_by_name ("fstat", &val);
269
270 /* Generate the form of ftag data that GDB expects. */
271 top = (fp->fstat >> 11) & 0x7;
272 val = 0;
273 for (i = 7; i >= 0; i--)
274 {
275 int tag;
73725ff3 276 if (fp->ftag & (1 << i))
58caa3dc
DJ
277 tag = i387_ftag (fp, (i + 8 - top) % 8);
278 else
279 tag = 3;
280 val |= tag << (2 * i);
281 }
282 supply_register_by_name ("ftag", &val);
283
284 val = fp->fiseg & 0xFFFF;
285 supply_register_by_name ("fiseg", &val);
286
287 val = fp->foseg & 0xFFFF;
288 supply_register_by_name ("foseg", &val);
289
290 val = (fp->fop) & 0x7FF;
291 supply_register_by_name ("fop", &val);
292}
This page took 0.588743 seconds and 4 git commands to generate.