2012-03-08 Stan Shebs <stan@codesourcery.com>
[deliverable/binutils-gdb.git] / gdb / gdbserver / i387-fp.c
CommitLineData
58caa3dc 1/* i387-specific utility functions, for the remote server for GDB.
28e7fd62 2 Copyright (C) 2000-2013 Free Software Foundation, Inc.
58caa3dc
DJ
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
a9762ec7 8 the Free Software Foundation; either version 3 of the License, or
58caa3dc
DJ
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
a9762ec7 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
58caa3dc
DJ
18
19#include "server.h"
0d62e5e8 20#include "i387-fp.h"
1570b33e 21#include "i386-xstate.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
1570b33e
L
75struct i387_xsave {
76 /* All these are only sixteen bits, plus padding, except for fop (which
77 is only eleven bits), and fooff / fioff (which are 32 bits each). */
78 unsigned short fctrl;
79 unsigned short fstat;
80 unsigned short ftag;
81 unsigned short fop;
82 unsigned int fioff;
83 unsigned short fiseg;
84 unsigned short pad1;
85 unsigned int fooff;
86 unsigned short foseg;
87 unsigned short pad12;
88
89 unsigned int mxcsr;
90 unsigned int mxcsr_mask;
91
92 /* Space for eight 80-bit FP values in 128-bit spaces. */
93 unsigned char st_space[128];
94
95 /* Space for eight 128-bit XMM values, or 16 on x86-64. */
96 unsigned char xmm_space[256];
97
98 unsigned char reserved1[48];
99
100 /* The extended control register 0 (the XFEATURE_ENABLED_MASK
101 register). */
102 unsigned long long xcr0;
103
104 unsigned char reserved2[40];
105
106 /* The XSTATE_BV bit vector. */
107 unsigned long long xstate_bv;
108
109 unsigned char reserved3[56];
110
111 /* Space for eight upper 128-bit YMM values, or 16 on x86-64. */
112 unsigned char ymmh_space[256];
113};
114
58caa3dc 115void
442ea881 116i387_cache_to_fsave (struct regcache *regcache, void *buf)
58caa3dc
DJ
117{
118 struct i387_fsave *fp = (struct i387_fsave *) buf;
119 int i;
120 int st0_regnum = find_regno ("st0");
121 unsigned long val, val2;
122
123 for (i = 0; i < 8; i++)
442ea881
PA
124 collect_register (regcache, i + st0_regnum,
125 ((char *) &fp->st_space[0]) + i * 10);
58caa3dc 126
442ea881
PA
127 collect_register_by_name (regcache, "fioff", &fp->fioff);
128 collect_register_by_name (regcache, "fooff", &fp->fooff);
58caa3dc
DJ
129
130 /* This one's 11 bits... */
442ea881 131 collect_register_by_name (regcache, "fop", &val2);
58caa3dc
DJ
132 fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
133
134 /* Some registers are 16-bit. */
442ea881 135 collect_register_by_name (regcache, "fctrl", &val);
0c2ead7e 136 fp->fctrl = val;
58caa3dc 137
442ea881 138 collect_register_by_name (regcache, "fstat", &val);
58caa3dc 139 val &= 0xFFFF;
0c2ead7e 140 fp->fstat = val;
58caa3dc 141
442ea881 142 collect_register_by_name (regcache, "ftag", &val);
58caa3dc 143 val &= 0xFFFF;
0c2ead7e 144 fp->ftag = val;
58caa3dc 145
442ea881 146 collect_register_by_name (regcache, "fiseg", &val);
58caa3dc 147 val &= 0xFFFF;
0c2ead7e 148 fp->fiseg = val;
58caa3dc 149
442ea881 150 collect_register_by_name (regcache, "foseg", &val);
58caa3dc 151 val &= 0xFFFF;
0c2ead7e 152 fp->foseg = val;
58caa3dc
DJ
153}
154
155void
442ea881 156i387_fsave_to_cache (struct regcache *regcache, const void *buf)
58caa3dc
DJ
157{
158 struct i387_fsave *fp = (struct i387_fsave *) buf;
159 int i;
160 int st0_regnum = find_regno ("st0");
161 unsigned long val;
162
163 for (i = 0; i < 8; i++)
442ea881
PA
164 supply_register (regcache, i + st0_regnum,
165 ((char *) &fp->st_space[0]) + i * 10);
58caa3dc 166
442ea881
PA
167 supply_register_by_name (regcache, "fioff", &fp->fioff);
168 supply_register_by_name (regcache, "fooff", &fp->fooff);
1b3f6016 169
58caa3dc
DJ
170 /* Some registers are 16-bit. */
171 val = fp->fctrl & 0xFFFF;
442ea881 172 supply_register_by_name (regcache, "fctrl", &val);
58caa3dc
DJ
173
174 val = fp->fstat & 0xFFFF;
442ea881 175 supply_register_by_name (regcache, "fstat", &val);
58caa3dc
DJ
176
177 val = fp->ftag & 0xFFFF;
442ea881 178 supply_register_by_name (regcache, "ftag", &val);
58caa3dc
DJ
179
180 val = fp->fiseg & 0xFFFF;
442ea881 181 supply_register_by_name (regcache, "fiseg", &val);
58caa3dc
DJ
182
183 val = fp->foseg & 0xFFFF;
442ea881 184 supply_register_by_name (regcache, "foseg", &val);
58caa3dc 185
0c2ead7e 186 /* fop has only 11 valid bits. */
58caa3dc 187 val = (fp->fop) & 0x7FF;
442ea881 188 supply_register_by_name (regcache, "fop", &val);
58caa3dc
DJ
189}
190
191void
442ea881 192i387_cache_to_fxsave (struct regcache *regcache, void *buf)
58caa3dc
DJ
193{
194 struct i387_fxsave *fp = (struct i387_fxsave *) buf;
195 int i;
196 int st0_regnum = find_regno ("st0");
197 int xmm0_regnum = find_regno ("xmm0");
198 unsigned long val, val2;
199
200 for (i = 0; i < 8; i++)
442ea881
PA
201 collect_register (regcache, i + st0_regnum,
202 ((char *) &fp->st_space[0]) + i * 16);
58caa3dc 203 for (i = 0; i < num_xmm_registers; i++)
442ea881
PA
204 collect_register (regcache, i + xmm0_regnum,
205 ((char *) &fp->xmm_space[0]) + i * 16);
58caa3dc 206
442ea881
PA
207 collect_register_by_name (regcache, "fioff", &fp->fioff);
208 collect_register_by_name (regcache, "fooff", &fp->fooff);
209 collect_register_by_name (regcache, "mxcsr", &fp->mxcsr);
1b3f6016 210
58caa3dc 211 /* This one's 11 bits... */
442ea881 212 collect_register_by_name (regcache, "fop", &val2);
58caa3dc
DJ
213 fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
214
215 /* Some registers are 16-bit. */
442ea881 216 collect_register_by_name (regcache, "fctrl", &val);
0c2ead7e 217 fp->fctrl = val;
58caa3dc 218
442ea881 219 collect_register_by_name (regcache, "fstat", &val);
0c2ead7e 220 fp->fstat = val;
58caa3dc
DJ
221
222 /* Convert to the simplifed tag form stored in fxsave data. */
442ea881 223 collect_register_by_name (regcache, "ftag", &val);
58caa3dc 224 val &= 0xFFFF;
73725ff3 225 val2 = 0;
58caa3dc
DJ
226 for (i = 7; i >= 0; i--)
227 {
228 int tag = (val >> (i * 2)) & 3;
229
230 if (tag != 3)
231 val2 |= (1 << i);
232 }
0c2ead7e 233 fp->ftag = val2;
58caa3dc 234
442ea881 235 collect_register_by_name (regcache, "fiseg", &val);
0c2ead7e 236 fp->fiseg = val;
58caa3dc 237
442ea881 238 collect_register_by_name (regcache, "foseg", &val);
0c2ead7e 239 fp->foseg = val;
58caa3dc
DJ
240}
241
1570b33e
L
242void
243i387_cache_to_xsave (struct regcache *regcache, void *buf)
244{
245 struct i387_xsave *fp = (struct i387_xsave *) buf;
246 int i;
247 unsigned long val, val2;
248 unsigned int clear_bv;
249 unsigned long long xstate_bv = 0;
250 char raw[16];
251 char *p;
252
253 /* The supported bits in `xstat_bv' are 1 byte. Clear part in
254 vector registers if its bit in xstat_bv is zero. */
255 clear_bv = (~fp->xstate_bv) & x86_xcr0;
256
257 /* Clear part in x87 and vector registers if its bit in xstat_bv is
258 zero. */
259 if (clear_bv)
260 {
261 if ((clear_bv & I386_XSTATE_X87))
262 for (i = 0; i < 8; i++)
263 memset (((char *) &fp->st_space[0]) + i * 16, 0, 10);
264
265 if ((clear_bv & I386_XSTATE_SSE))
266 for (i = 0; i < num_xmm_registers; i++)
267 memset (((char *) &fp->xmm_space[0]) + i * 16, 0, 16);
268
269 if ((clear_bv & I386_XSTATE_AVX))
270 for (i = 0; i < num_xmm_registers; i++)
271 memset (((char *) &fp->ymmh_space[0]) + i * 16, 0, 16);
272 }
273
274 /* Check if any x87 registers are changed. */
275 if ((x86_xcr0 & I386_XSTATE_X87))
276 {
277 int st0_regnum = find_regno ("st0");
278
279 for (i = 0; i < 8; i++)
280 {
281 collect_register (regcache, i + st0_regnum, raw);
282 p = ((char *) &fp->st_space[0]) + i * 16;
283 if (memcmp (raw, p, 10))
284 {
285 xstate_bv |= I386_XSTATE_X87;
286 memcpy (p, raw, 10);
287 }
288 }
289 }
290
291 /* Check if any SSE registers are changed. */
292 if ((x86_xcr0 & I386_XSTATE_SSE))
293 {
294 int xmm0_regnum = find_regno ("xmm0");
295
296 for (i = 0; i < num_xmm_registers; i++)
297 {
298 collect_register (regcache, i + xmm0_regnum, raw);
299 p = ((char *) &fp->xmm_space[0]) + i * 16;
300 if (memcmp (raw, p, 16))
301 {
302 xstate_bv |= I386_XSTATE_SSE;
303 memcpy (p, raw, 16);
304 }
305 }
306 }
307
308 /* Check if any AVX registers are changed. */
309 if ((x86_xcr0 & I386_XSTATE_AVX))
310 {
311 int ymm0h_regnum = find_regno ("ymm0h");
312
313 for (i = 0; i < num_xmm_registers; i++)
314 {
315 collect_register (regcache, i + ymm0h_regnum, raw);
316 p = ((char *) &fp->ymmh_space[0]) + i * 16;
317 if (memcmp (raw, p, 16))
318 {
319 xstate_bv |= I386_XSTATE_AVX;
320 memcpy (p, raw, 16);
321 }
322 }
323 }
324
325 /* Update the corresponding bits in xstate_bv if any SSE/AVX
326 registers are changed. */
327 fp->xstate_bv |= xstate_bv;
328
329 collect_register_by_name (regcache, "fioff", &fp->fioff);
330 collect_register_by_name (regcache, "fooff", &fp->fooff);
331 collect_register_by_name (regcache, "mxcsr", &fp->mxcsr);
332
333 /* This one's 11 bits... */
334 collect_register_by_name (regcache, "fop", &val2);
335 fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
336
337 /* Some registers are 16-bit. */
338 collect_register_by_name (regcache, "fctrl", &val);
339 fp->fctrl = val;
340
341 collect_register_by_name (regcache, "fstat", &val);
342 fp->fstat = val;
343
344 /* Convert to the simplifed tag form stored in fxsave data. */
345 collect_register_by_name (regcache, "ftag", &val);
346 val &= 0xFFFF;
347 val2 = 0;
348 for (i = 7; i >= 0; i--)
349 {
350 int tag = (val >> (i * 2)) & 3;
351
352 if (tag != 3)
353 val2 |= (1 << i);
354 }
355 fp->ftag = val2;
356
357 collect_register_by_name (regcache, "fiseg", &val);
358 fp->fiseg = val;
359
360 collect_register_by_name (regcache, "foseg", &val);
361 fp->foseg = val;
362}
363
58caa3dc
DJ
364static int
365i387_ftag (struct i387_fxsave *fp, int regno)
366{
367 unsigned char *raw = &fp->st_space[regno * 16];
368 unsigned int exponent;
369 unsigned long fraction[2];
370 int integer;
371
372 integer = raw[7] & 0x80;
373 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
374 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
375 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
1b3f6016 376 | (raw[5] << 8) | raw[4]);
58caa3dc
DJ
377
378 if (exponent == 0x7fff)
379 {
380 /* Special. */
381 return (2);
382 }
383 else if (exponent == 0x0000)
384 {
385 if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
1b3f6016
PA
386 {
387 /* Zero. */
388 return (1);
389 }
58caa3dc 390 else
1b3f6016
PA
391 {
392 /* Special. */
393 return (2);
394 }
58caa3dc
DJ
395 }
396 else
397 {
398 if (integer)
1b3f6016
PA
399 {
400 /* Valid. */
401 return (0);
402 }
58caa3dc 403 else
1b3f6016
PA
404 {
405 /* Special. */
406 return (2);
407 }
58caa3dc
DJ
408 }
409}
410
411void
442ea881 412i387_fxsave_to_cache (struct regcache *regcache, const void *buf)
58caa3dc
DJ
413{
414 struct i387_fxsave *fp = (struct i387_fxsave *) buf;
415 int i, top;
416 int st0_regnum = find_regno ("st0");
417 int xmm0_regnum = find_regno ("xmm0");
418 unsigned long val;
419
420 for (i = 0; i < 8; i++)
442ea881
PA
421 supply_register (regcache, i + st0_regnum,
422 ((char *) &fp->st_space[0]) + i * 16);
58caa3dc 423 for (i = 0; i < num_xmm_registers; i++)
442ea881
PA
424 supply_register (regcache, i + xmm0_regnum,
425 ((char *) &fp->xmm_space[0]) + i * 16);
58caa3dc 426
442ea881
PA
427 supply_register_by_name (regcache, "fioff", &fp->fioff);
428 supply_register_by_name (regcache, "fooff", &fp->fooff);
429 supply_register_by_name (regcache, "mxcsr", &fp->mxcsr);
1b3f6016 430
58caa3dc
DJ
431 /* Some registers are 16-bit. */
432 val = fp->fctrl & 0xFFFF;
442ea881 433 supply_register_by_name (regcache, "fctrl", &val);
58caa3dc
DJ
434
435 val = fp->fstat & 0xFFFF;
442ea881 436 supply_register_by_name (regcache, "fstat", &val);
58caa3dc
DJ
437
438 /* Generate the form of ftag data that GDB expects. */
439 top = (fp->fstat >> 11) & 0x7;
440 val = 0;
441 for (i = 7; i >= 0; i--)
442 {
443 int tag;
73725ff3 444 if (fp->ftag & (1 << i))
58caa3dc
DJ
445 tag = i387_ftag (fp, (i + 8 - top) % 8);
446 else
447 tag = 3;
448 val |= tag << (2 * i);
449 }
442ea881 450 supply_register_by_name (regcache, "ftag", &val);
58caa3dc
DJ
451
452 val = fp->fiseg & 0xFFFF;
442ea881 453 supply_register_by_name (regcache, "fiseg", &val);
58caa3dc
DJ
454
455 val = fp->foseg & 0xFFFF;
442ea881 456 supply_register_by_name (regcache, "foseg", &val);
58caa3dc
DJ
457
458 val = (fp->fop) & 0x7FF;
442ea881 459 supply_register_by_name (regcache, "fop", &val);
58caa3dc 460}
1570b33e
L
461
462void
463i387_xsave_to_cache (struct regcache *regcache, const void *buf)
464{
465 struct i387_xsave *fp = (struct i387_xsave *) buf;
466 struct i387_fxsave *fxp = (struct i387_fxsave *) buf;
467 int i, top;
468 unsigned long val;
469 unsigned int clear_bv;
85724a0e 470 gdb_byte *p;
1570b33e
L
471
472 /* The supported bits in `xstat_bv' are 1 byte. Clear part in
473 vector registers if its bit in xstat_bv is zero. */
474 clear_bv = (~fp->xstate_bv) & x86_xcr0;
475
476 /* Check if any x87 registers are changed. */
85724a0e 477 if ((x86_xcr0 & I386_XSTATE_X87) != 0)
1570b33e
L
478 {
479 int st0_regnum = find_regno ("st0");
480
85724a0e
PA
481 if ((clear_bv & I386_XSTATE_X87) != 0)
482 {
483 for (i = 0; i < 8; i++)
1c79eb8a 484 supply_register_zeroed (regcache, i + st0_regnum);
85724a0e 485 }
1570b33e 486 else
1570b33e 487 {
85724a0e
PA
488 p = (gdb_byte *) &fp->st_space[0];
489 for (i = 0; i < 8; i++)
490 supply_register (regcache, i + st0_regnum, p + i * 16);
1570b33e
L
491 }
492 }
493
85724a0e 494 if ((x86_xcr0 & I386_XSTATE_SSE) != 0)
1570b33e
L
495 {
496 int xmm0_regnum = find_regno ("xmm0");
497
498 if ((clear_bv & I386_XSTATE_SSE))
85724a0e
PA
499 {
500 for (i = 0; i < num_xmm_registers; i++)
1c79eb8a 501 supply_register_zeroed (regcache, i + xmm0_regnum);
85724a0e 502 }
1570b33e 503 else
1570b33e 504 {
85724a0e
PA
505 p = (gdb_byte *) &fp->xmm_space[0];
506 for (i = 0; i < num_xmm_registers; i++)
507 supply_register (regcache, i + xmm0_regnum, p + i * 16);
1570b33e
L
508 }
509 }
510
85724a0e 511 if ((x86_xcr0 & I386_XSTATE_AVX) != 0)
1570b33e
L
512 {
513 int ymm0h_regnum = find_regno ("ymm0h");
514
85724a0e
PA
515 if ((clear_bv & I386_XSTATE_AVX) != 0)
516 {
517 for (i = 0; i < num_xmm_registers; i++)
1c79eb8a 518 supply_register_zeroed (regcache, i + ymm0h_regnum);
85724a0e 519 }
1570b33e 520 else
1570b33e 521 {
85724a0e
PA
522 p = (gdb_byte *) &fp->ymmh_space[0];
523 for (i = 0; i < num_xmm_registers; i++)
524 supply_register (regcache, i + ymm0h_regnum, p + i * 16);
1570b33e
L
525 }
526 }
527
528 supply_register_by_name (regcache, "fioff", &fp->fioff);
529 supply_register_by_name (regcache, "fooff", &fp->fooff);
530 supply_register_by_name (regcache, "mxcsr", &fp->mxcsr);
531
532 /* Some registers are 16-bit. */
533 val = fp->fctrl & 0xFFFF;
534 supply_register_by_name (regcache, "fctrl", &val);
535
536 val = fp->fstat & 0xFFFF;
537 supply_register_by_name (regcache, "fstat", &val);
538
539 /* Generate the form of ftag data that GDB expects. */
540 top = (fp->fstat >> 11) & 0x7;
541 val = 0;
542 for (i = 7; i >= 0; i--)
543 {
544 int tag;
545 if (fp->ftag & (1 << i))
546 tag = i387_ftag (fxp, (i + 8 - top) % 8);
547 else
548 tag = 3;
549 val |= tag << (2 * i);
550 }
551 supply_register_by_name (regcache, "ftag", &val);
552
553 val = fp->fiseg & 0xFFFF;
554 supply_register_by_name (regcache, "fiseg", &val);
555
556 val = fp->foseg & 0xFFFF;
557 supply_register_by_name (regcache, "foseg", &val);
558
559 val = (fp->fop) & 0x7FF;
560 supply_register_by_name (regcache, "fop", &val);
561}
562
563/* Default to SSE. */
564unsigned long long x86_xcr0 = I386_XSTATE_SSE_MASK;
This page took 0.814374 seconds and 4 git commands to generate.