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