gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdbserver / i387-fp.cc
CommitLineData
58caa3dc 1/* i387-specific utility functions, for the remote server for GDB.
b811d2c2 2 Copyright (C) 2000-2020 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"
268a13a5 21#include "gdbsupport/x86-xstate.h"
58caa3dc 22
a196ebeb
WT
23static const int num_mpx_bnd_registers = 4;
24static const int num_mpx_cfg_registers = 2;
01f9f808
MS
25static const int num_avx512_k_registers = 8;
26static const int num_avx512_zmmh_low_registers = 16;
27static const int num_avx512_zmmh_high_registers = 16;
28static const int num_avx512_ymmh_registers = 16;
29static const int num_avx512_xmm_registers = 16;
51547df6 30static const int num_pkeys_registers = 1;
a196ebeb 31
58caa3dc
DJ
32/* Note: These functions preserve the reserved bits in control registers.
33 However, gdbserver promptly throws away that information. */
34
35/* These structs should have the proper sizes and alignment on both
36 i386 and x86-64 machines. */
37
38struct i387_fsave {
39 /* All these are only sixteen bits, plus padding, except for fop (which
40 is only eleven bits), and fooff / fioff (which are 32 bits each). */
0c2ead7e
DJ
41 unsigned short fctrl;
42 unsigned short pad1;
43 unsigned short fstat;
44 unsigned short pad2;
45 unsigned short ftag;
46 unsigned short pad3;
58caa3dc
DJ
47 unsigned int fioff;
48 unsigned short fiseg;
49 unsigned short fop;
50 unsigned int fooff;
0c2ead7e
DJ
51 unsigned short foseg;
52 unsigned short pad4;
58caa3dc
DJ
53
54 /* Space for eight 80-bit FP values. */
f450004a 55 unsigned char st_space[80];
58caa3dc
DJ
56};
57
58struct i387_fxsave {
59 /* All these are only sixteen bits, plus padding, except for fop (which
60 is only eleven bits), and fooff / fioff (which are 32 bits each). */
61 unsigned short fctrl;
62 unsigned short fstat;
63 unsigned short ftag;
64 unsigned short fop;
65 unsigned int fioff;
0c2ead7e
DJ
66 unsigned short fiseg;
67 unsigned short pad1;
58caa3dc 68 unsigned int fooff;
0c2ead7e
DJ
69 unsigned short foseg;
70 unsigned short pad12;
58caa3dc
DJ
71
72 unsigned int mxcsr;
0c2ead7e 73 unsigned int pad3;
58caa3dc
DJ
74
75 /* Space for eight 80-bit FP values in 128-bit spaces. */
f450004a 76 unsigned char st_space[128];
58caa3dc
DJ
77
78 /* Space for eight 128-bit XMM values, or 16 on x86-64. */
f450004a 79 unsigned char xmm_space[256];
58caa3dc
DJ
80};
81
1570b33e
L
82struct i387_xsave {
83 /* All these are only sixteen bits, plus padding, except for fop (which
84 is only eleven bits), and fooff / fioff (which are 32 bits each). */
85 unsigned short fctrl;
86 unsigned short fstat;
87 unsigned short ftag;
88 unsigned short fop;
89 unsigned int fioff;
90 unsigned short fiseg;
91 unsigned short pad1;
92 unsigned int fooff;
93 unsigned short foseg;
94 unsigned short pad12;
95
96 unsigned int mxcsr;
97 unsigned int mxcsr_mask;
98
99 /* Space for eight 80-bit FP values in 128-bit spaces. */
100 unsigned char st_space[128];
101
102 /* Space for eight 128-bit XMM values, or 16 on x86-64. */
103 unsigned char xmm_space[256];
104
105 unsigned char reserved1[48];
106
107 /* The extended control register 0 (the XFEATURE_ENABLED_MASK
108 register). */
109 unsigned long long xcr0;
110
111 unsigned char reserved2[40];
112
113 /* The XSTATE_BV bit vector. */
114 unsigned long long xstate_bv;
115
116 unsigned char reserved3[56];
117
118 /* Space for eight upper 128-bit YMM values, or 16 on x86-64. */
119 unsigned char ymmh_space[256];
a196ebeb
WT
120
121 unsigned char reserved4[128];
122
123 /* Space for 4 bound registers values of 128 bits. */
124 unsigned char mpx_bnd_space[64];
125
126 /* Space for 2 MPX configuration registers of 64 bits
127 plus reserved space. */
128 unsigned char mpx_cfg_space[16];
01f9f808
MS
129
130 unsigned char reserved5[48];
131
132 /* Space for 8 OpMask register values of 64 bits. */
133 unsigned char k_space[64];
134
135 /* Space for 16 256-bit zmm0-15. */
136 unsigned char zmmh_low_space[512];
137
138 /* Space for 16 512-bit zmm16-31 values. */
139 unsigned char zmmh_high_space[1024];
51547df6
MS
140
141 /* Space for 1 32-bit PKRU register. The HW XSTATE size for this feature is
142 actually 64 bits, but WRPKRU/RDPKRU instructions ignore upper 32 bits. */
143 unsigned char pkru_space[8];
1570b33e
L
144};
145
58caa3dc 146void
442ea881 147i387_cache_to_fsave (struct regcache *regcache, void *buf)
58caa3dc
DJ
148{
149 struct i387_fsave *fp = (struct i387_fsave *) buf;
150 int i;
3aee8918 151 int st0_regnum = find_regno (regcache->tdesc, "st0");
cb197132 152 unsigned long val2;
58caa3dc
DJ
153
154 for (i = 0; i < 8; i++)
442ea881
PA
155 collect_register (regcache, i + st0_regnum,
156 ((char *) &fp->st_space[0]) + i * 10);
58caa3dc 157
cb197132
PA
158 fp->fioff = regcache_raw_get_unsigned_by_name (regcache, "fioff");
159 fp->fooff = regcache_raw_get_unsigned_by_name (regcache, "fooff");
160
58caa3dc 161 /* This one's 11 bits... */
cb197132 162 val2 = regcache_raw_get_unsigned_by_name (regcache, "fop");
58caa3dc
DJ
163 fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
164
165 /* Some registers are 16-bit. */
cb197132
PA
166 fp->fctrl = regcache_raw_get_unsigned_by_name (regcache, "fctrl");
167 fp->fstat = regcache_raw_get_unsigned_by_name (regcache, "fstat");
168 fp->ftag = regcache_raw_get_unsigned_by_name (regcache, "ftag");
169 fp->fiseg = regcache_raw_get_unsigned_by_name (regcache, "fiseg");
170 fp->foseg = regcache_raw_get_unsigned_by_name (regcache, "foseg");
58caa3dc
DJ
171}
172
173void
442ea881 174i387_fsave_to_cache (struct regcache *regcache, const void *buf)
58caa3dc
DJ
175{
176 struct i387_fsave *fp = (struct i387_fsave *) buf;
177 int i;
3aee8918 178 int st0_regnum = find_regno (regcache->tdesc, "st0");
58caa3dc
DJ
179 unsigned long val;
180
181 for (i = 0; i < 8; i++)
442ea881
PA
182 supply_register (regcache, i + st0_regnum,
183 ((char *) &fp->st_space[0]) + i * 10);
58caa3dc 184
442ea881
PA
185 supply_register_by_name (regcache, "fioff", &fp->fioff);
186 supply_register_by_name (regcache, "fooff", &fp->fooff);
1b3f6016 187
58caa3dc
DJ
188 /* Some registers are 16-bit. */
189 val = fp->fctrl & 0xFFFF;
442ea881 190 supply_register_by_name (regcache, "fctrl", &val);
58caa3dc
DJ
191
192 val = fp->fstat & 0xFFFF;
442ea881 193 supply_register_by_name (regcache, "fstat", &val);
58caa3dc
DJ
194
195 val = fp->ftag & 0xFFFF;
442ea881 196 supply_register_by_name (regcache, "ftag", &val);
58caa3dc
DJ
197
198 val = fp->fiseg & 0xFFFF;
442ea881 199 supply_register_by_name (regcache, "fiseg", &val);
58caa3dc
DJ
200
201 val = fp->foseg & 0xFFFF;
442ea881 202 supply_register_by_name (regcache, "foseg", &val);
58caa3dc 203
0c2ead7e 204 /* fop has only 11 valid bits. */
58caa3dc 205 val = (fp->fop) & 0x7FF;
442ea881 206 supply_register_by_name (regcache, "fop", &val);
58caa3dc
DJ
207}
208
209void
442ea881 210i387_cache_to_fxsave (struct regcache *regcache, void *buf)
58caa3dc
DJ
211{
212 struct i387_fxsave *fp = (struct i387_fxsave *) buf;
213 int i;
3aee8918
PA
214 int st0_regnum = find_regno (regcache->tdesc, "st0");
215 int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
58caa3dc 216 unsigned long val, val2;
3aee8918
PA
217 /* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
218 int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
58caa3dc
DJ
219
220 for (i = 0; i < 8; i++)
442ea881
PA
221 collect_register (regcache, i + st0_regnum,
222 ((char *) &fp->st_space[0]) + i * 16);
58caa3dc 223 for (i = 0; i < num_xmm_registers; i++)
442ea881
PA
224 collect_register (regcache, i + xmm0_regnum,
225 ((char *) &fp->xmm_space[0]) + i * 16);
58caa3dc 226
cb197132
PA
227 fp->fioff = regcache_raw_get_unsigned_by_name (regcache, "fioff");
228 fp->fooff = regcache_raw_get_unsigned_by_name (regcache, "fooff");
229 fp->mxcsr = regcache_raw_get_unsigned_by_name (regcache, "mxcsr");
1b3f6016 230
58caa3dc 231 /* This one's 11 bits... */
cb197132 232 val2 = regcache_raw_get_unsigned_by_name (regcache, "fop");
58caa3dc
DJ
233 fp->fop = (val2 & 0x7FF) | (fp->fop & 0xF800);
234
235 /* Some registers are 16-bit. */
cb197132
PA
236 fp->fctrl = regcache_raw_get_unsigned_by_name (regcache, "fctrl");
237 fp->fstat = regcache_raw_get_unsigned_by_name (regcache, "fstat");
58caa3dc
DJ
238
239 /* Convert to the simplifed tag form stored in fxsave data. */
cb197132 240 val = regcache_raw_get_unsigned_by_name (regcache, "ftag");
73725ff3 241 val2 = 0;
58caa3dc
DJ
242 for (i = 7; i >= 0; i--)
243 {
244 int tag = (val >> (i * 2)) & 3;
245
246 if (tag != 3)
247 val2 |= (1 << i);
248 }
0c2ead7e 249 fp->ftag = val2;
58caa3dc 250
cb197132
PA
251 fp->fiseg = regcache_raw_get_unsigned_by_name (regcache, "fiseg");
252 fp->foseg = regcache_raw_get_unsigned_by_name (regcache, "foseg");
58caa3dc
DJ
253}
254
1570b33e
L
255void
256i387_cache_to_xsave (struct regcache *regcache, void *buf)
257{
258 struct i387_xsave *fp = (struct i387_xsave *) buf;
259 int i;
260 unsigned long val, val2;
1570b33e 261 unsigned long long xstate_bv = 0;
ff6527bb 262 unsigned long long clear_bv = 0;
01f9f808 263 char raw[64];
1570b33e 264 char *p;
3aee8918
PA
265 /* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
266 int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
1570b33e 267
ff6527bb 268 /* The supported bits in `xstat_bv' are 8 bytes. Clear part in
1570b33e
L
269 vector registers if its bit in xstat_bv is zero. */
270 clear_bv = (~fp->xstate_bv) & x86_xcr0;
271
272 /* Clear part in x87 and vector registers if its bit in xstat_bv is
273 zero. */
274 if (clear_bv)
275 {
df7e5265 276 if ((clear_bv & X86_XSTATE_X87))
8ee22052
AB
277 {
278 for (i = 0; i < 8; i++)
279 memset (((char *) &fp->st_space[0]) + i * 16, 0, 10);
280
281 fp->fioff = 0;
282 fp->fooff = 0;
283 fp->fctrl = I387_FCTRL_INIT_VAL;
284 fp->fstat = 0;
285 fp->ftag = 0;
286 fp->fiseg = 0;
287 fp->foseg = 0;
288 fp->fop = 0;
289 }
1570b33e 290
df7e5265 291 if ((clear_bv & X86_XSTATE_SSE))
8ee22052 292 for (i = 0; i < num_xmm_registers; i++)
1570b33e
L
293 memset (((char *) &fp->xmm_space[0]) + i * 16, 0, 16);
294
df7e5265 295 if ((clear_bv & X86_XSTATE_AVX))
8ee22052 296 for (i = 0; i < num_xmm_registers; i++)
1570b33e 297 memset (((char *) &fp->ymmh_space[0]) + i * 16, 0, 16);
a196ebeb 298
8ee22052
AB
299 if ((clear_bv & X86_XSTATE_SSE) && (clear_bv & X86_XSTATE_AVX))
300 memset (((char *) &fp->mxcsr), 0, 4);
301
df7e5265 302 if ((clear_bv & X86_XSTATE_BNDREGS))
a196ebeb
WT
303 for (i = 0; i < num_mpx_bnd_registers; i++)
304 memset (((char *) &fp->mpx_bnd_space[0]) + i * 16, 0, 16);
305
df7e5265 306 if ((clear_bv & X86_XSTATE_BNDCFG))
a196ebeb
WT
307 for (i = 0; i < num_mpx_cfg_registers; i++)
308 memset (((char *) &fp->mpx_cfg_space[0]) + i * 8, 0, 8);
01f9f808 309
df7e5265 310 if ((clear_bv & X86_XSTATE_K))
01f9f808
MS
311 for (i = 0; i < num_avx512_k_registers; i++)
312 memset (((char *) &fp->k_space[0]) + i * 8, 0, 8);
313
df7e5265 314 if ((clear_bv & X86_XSTATE_ZMM_H))
01f9f808
MS
315 for (i = 0; i < num_avx512_zmmh_low_registers; i++)
316 memset (((char *) &fp->zmmh_low_space[0]) + i * 32, 0, 32);
317
df7e5265 318 if ((clear_bv & X86_XSTATE_ZMM))
01f9f808
MS
319 {
320 for (i = 0; i < num_avx512_zmmh_high_registers; i++)
321 memset (((char *) &fp->zmmh_low_space[0]) + 32 + i * 64, 0, 32);
322 for (i = 0; i < num_avx512_xmm_registers; i++)
323 memset (((char *) &fp->zmmh_high_space[0]) + i * 64, 0, 16);
324 for (i = 0; i < num_avx512_ymmh_registers; i++)
325 memset (((char *) &fp->zmmh_high_space[0]) + 16 + i * 64, 0, 16);
326 }
51547df6
MS
327
328 if ((clear_bv & X86_XSTATE_PKRU))
329 for (i = 0; i < num_pkeys_registers; i++)
330 memset (((char *) &fp->pkru_space[0]) + i * 4, 0, 4);
1570b33e
L
331 }
332
333 /* Check if any x87 registers are changed. */
df7e5265 334 if ((x86_xcr0 & X86_XSTATE_X87))
1570b33e 335 {
3aee8918 336 int st0_regnum = find_regno (regcache->tdesc, "st0");
1570b33e
L
337
338 for (i = 0; i < 8; i++)
339 {
340 collect_register (regcache, i + st0_regnum, raw);
341 p = ((char *) &fp->st_space[0]) + i * 16;
342 if (memcmp (raw, p, 10))
343 {
df7e5265 344 xstate_bv |= X86_XSTATE_X87;
1570b33e
L
345 memcpy (p, raw, 10);
346 }
347 }
348 }
349
350 /* Check if any SSE registers are changed. */
df7e5265 351 if ((x86_xcr0 & X86_XSTATE_SSE))
1570b33e 352 {
3aee8918 353 int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
1570b33e
L
354
355 for (i = 0; i < num_xmm_registers; i++)
356 {
357 collect_register (regcache, i + xmm0_regnum, raw);
358 p = ((char *) &fp->xmm_space[0]) + i * 16;
359 if (memcmp (raw, p, 16))
360 {
df7e5265 361 xstate_bv |= X86_XSTATE_SSE;
1570b33e
L
362 memcpy (p, raw, 16);
363 }
364 }
365 }
366
367 /* Check if any AVX registers are changed. */
df7e5265 368 if ((x86_xcr0 & X86_XSTATE_AVX))
1570b33e 369 {
3aee8918 370 int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h");
1570b33e
L
371
372 for (i = 0; i < num_xmm_registers; i++)
373 {
374 collect_register (regcache, i + ymm0h_regnum, raw);
375 p = ((char *) &fp->ymmh_space[0]) + i * 16;
376 if (memcmp (raw, p, 16))
377 {
df7e5265 378 xstate_bv |= X86_XSTATE_AVX;
1570b33e
L
379 memcpy (p, raw, 16);
380 }
381 }
382 }
383
a196ebeb 384 /* Check if any bound register has changed. */
df7e5265 385 if ((x86_xcr0 & X86_XSTATE_BNDREGS))
a196ebeb
WT
386 {
387 int bnd0r_regnum = find_regno (regcache->tdesc, "bnd0raw");
388
389 for (i = 0; i < num_mpx_bnd_registers; i++)
390 {
391 collect_register (regcache, i + bnd0r_regnum, raw);
392 p = ((char *) &fp->mpx_bnd_space[0]) + i * 16;
393 if (memcmp (raw, p, 16))
394 {
df7e5265 395 xstate_bv |= X86_XSTATE_BNDREGS;
a196ebeb
WT
396 memcpy (p, raw, 16);
397 }
398 }
399 }
400
401 /* Check if any status register has changed. */
df7e5265 402 if ((x86_xcr0 & X86_XSTATE_BNDCFG))
a196ebeb
WT
403 {
404 int bndcfg_regnum = find_regno (regcache->tdesc, "bndcfgu");
405
406 for (i = 0; i < num_mpx_cfg_registers; i++)
407 {
408 collect_register (regcache, i + bndcfg_regnum, raw);
409 p = ((char *) &fp->mpx_cfg_space[0]) + i * 8;
410 if (memcmp (raw, p, 8))
411 {
df7e5265 412 xstate_bv |= X86_XSTATE_BNDCFG;
a196ebeb
WT
413 memcpy (p, raw, 8);
414 }
415 }
416 }
417
01f9f808 418 /* Check if any K registers are changed. */
df7e5265 419 if ((x86_xcr0 & X86_XSTATE_K))
01f9f808
MS
420 {
421 int k0_regnum = find_regno (regcache->tdesc, "k0");
422
423 for (i = 0; i < num_avx512_k_registers; i++)
424 {
425 collect_register (regcache, i + k0_regnum, raw);
426 p = ((char *) &fp->k_space[0]) + i * 8;
427 if (memcmp (raw, p, 8) != 0)
428 {
df7e5265 429 xstate_bv |= X86_XSTATE_K;
01f9f808
MS
430 memcpy (p, raw, 8);
431 }
432 }
433 }
434
435 /* Check if any of ZMM0H-ZMM15H registers are changed. */
df7e5265 436 if ((x86_xcr0 & X86_XSTATE_ZMM_H))
01f9f808
MS
437 {
438 int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h");
439
440 for (i = 0; i < num_avx512_zmmh_low_registers; i++)
441 {
442 collect_register (regcache, i + zmm0h_regnum, raw);
443 p = ((char *) &fp->zmmh_low_space[0]) + i * 32;
444 if (memcmp (raw, p, 32) != 0)
445 {
df7e5265 446 xstate_bv |= X86_XSTATE_ZMM_H;
01f9f808
MS
447 memcpy (p, raw, 32);
448 }
449 }
450 }
451
452 /* Check if any of ZMM16H-ZMM31H registers are changed. */
df7e5265 453 if ((x86_xcr0 & X86_XSTATE_ZMM))
01f9f808
MS
454 {
455 int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
456
457 for (i = 0; i < num_avx512_zmmh_high_registers; i++)
458 {
459 collect_register (regcache, i + zmm16h_regnum, raw);
3368c1e5 460 p = ((char *) &fp->zmmh_high_space[0]) + 32 + i * 64;
01f9f808
MS
461 if (memcmp (raw, p, 32) != 0)
462 {
df7e5265 463 xstate_bv |= X86_XSTATE_ZMM;
01f9f808
MS
464 memcpy (p, raw, 32);
465 }
466 }
467 }
468
469 /* Check if any XMM_AVX512 registers are changed. */
df7e5265 470 if ((x86_xcr0 & X86_XSTATE_ZMM))
01f9f808
MS
471 {
472 int xmm_avx512_regnum = find_regno (regcache->tdesc, "xmm16");
473
474 for (i = 0; i < num_avx512_xmm_registers; i++)
475 {
476 collect_register (regcache, i + xmm_avx512_regnum, raw);
477 p = ((char *) &fp->zmmh_high_space[0]) + i * 64;
478 if (memcmp (raw, p, 16) != 0)
479 {
df7e5265 480 xstate_bv |= X86_XSTATE_ZMM;
01f9f808
MS
481 memcpy (p, raw, 16);
482 }
483 }
484 }
485
486 /* Check if any YMMH_AVX512 registers are changed. */
df7e5265 487 if ((x86_xcr0 & X86_XSTATE_ZMM))
01f9f808
MS
488 {
489 int ymmh_avx512_regnum = find_regno (regcache->tdesc, "ymm16h");
490
491 for (i = 0; i < num_avx512_ymmh_registers; i++)
492 {
493 collect_register (regcache, i + ymmh_avx512_regnum, raw);
494 p = ((char *) &fp->zmmh_high_space[0]) + 16 + i * 64;
495 if (memcmp (raw, p, 16) != 0)
496 {
df7e5265 497 xstate_bv |= X86_XSTATE_ZMM;
01f9f808
MS
498 memcpy (p, raw, 16);
499 }
500 }
501 }
502
51547df6
MS
503 /* Check if any PKEYS registers are changed. */
504 if ((x86_xcr0 & X86_XSTATE_PKRU))
505 {
506 int pkru_regnum = find_regno (regcache->tdesc, "pkru");
507
508 for (i = 0; i < num_pkeys_registers; i++)
509 {
510 collect_register (regcache, i + pkru_regnum, raw);
511 p = ((char *) &fp->pkru_space[0]) + i * 4;
512 if (memcmp (raw, p, 4) != 0)
513 {
514 xstate_bv |= X86_XSTATE_PKRU;
515 memcpy (p, raw, 4);
516 }
517 }
518 }
519
8ee22052
AB
520 if ((x86_xcr0 & X86_XSTATE_SSE) || (x86_xcr0 & X86_XSTATE_AVX))
521 {
522 collect_register_by_name (regcache, "mxcsr", raw);
523 if (memcmp (raw, &fp->mxcsr, 4) != 0)
524 {
525 if (((fp->xstate_bv | xstate_bv)
526 & (X86_XSTATE_SSE | X86_XSTATE_AVX)) == 0)
527 xstate_bv |= X86_XSTATE_SSE;
528 memcpy (&fp->mxcsr, raw, 4);
529 }
530 }
1570b33e 531
8ee22052
AB
532 if (x86_xcr0 & X86_XSTATE_X87)
533 {
534 collect_register_by_name (regcache, "fioff", raw);
535 if (memcmp (raw, &fp->fioff, 4) != 0)
536 {
537 xstate_bv |= X86_XSTATE_X87;
538 memcpy (&fp->fioff, raw, 4);
539 }
1570b33e 540
8ee22052
AB
541 collect_register_by_name (regcache, "fooff", raw);
542 if (memcmp (raw, &fp->fooff, 4) != 0)
543 {
544 xstate_bv |= X86_XSTATE_X87;
545 memcpy (&fp->fooff, raw, 4);
546 }
1570b33e 547
8ee22052 548 /* This one's 11 bits... */
cb197132 549 val2 = regcache_raw_get_unsigned_by_name (regcache, "fop");
8ee22052
AB
550 val2 = (val2 & 0x7FF) | (fp->fop & 0xF800);
551 if (fp->fop != val2)
552 {
553 xstate_bv |= X86_XSTATE_X87;
554 fp->fop = val2;
555 }
1570b33e 556
8ee22052 557 /* Some registers are 16-bit. */
cb197132 558 val = regcache_raw_get_unsigned_by_name (regcache, "fctrl");
8ee22052
AB
559 if (fp->fctrl != val)
560 {
561 xstate_bv |= X86_XSTATE_X87;
562 fp->fctrl = val;
563 }
1570b33e 564
cb197132 565 val = regcache_raw_get_unsigned_by_name (regcache, "fstat");
8ee22052
AB
566 if (fp->fstat != val)
567 {
568 xstate_bv |= X86_XSTATE_X87;
569 fp->fstat = val;
570 }
1570b33e 571
8ee22052 572 /* Convert to the simplifed tag form stored in fxsave data. */
cb197132 573 val = regcache_raw_get_unsigned_by_name (regcache, "ftag");
8ee22052
AB
574 val2 = 0;
575 for (i = 7; i >= 0; i--)
576 {
577 int tag = (val >> (i * 2)) & 3;
1570b33e 578
8ee22052
AB
579 if (tag != 3)
580 val2 |= (1 << i);
581 }
582 if (fp->ftag != val2)
583 {
584 xstate_bv |= X86_XSTATE_X87;
585 fp->ftag = val2;
586 }
1570b33e 587
cb197132 588 val = regcache_raw_get_unsigned_by_name (regcache, "fiseg");
8ee22052
AB
589 if (fp->fiseg != val)
590 {
591 xstate_bv |= X86_XSTATE_X87;
592 fp->fiseg = val;
593 }
594
cb197132 595 val = regcache_raw_get_unsigned_by_name (regcache, "foseg");
8ee22052
AB
596 if (fp->foseg != val)
597 {
598 xstate_bv |= X86_XSTATE_X87;
599 fp->foseg = val;
600 }
601 }
602
603 /* Update the corresponding bits in xstate_bv if any SSE/AVX
604 registers are changed. */
605 fp->xstate_bv |= xstate_bv;
1570b33e
L
606}
607
58caa3dc
DJ
608static int
609i387_ftag (struct i387_fxsave *fp, int regno)
610{
611 unsigned char *raw = &fp->st_space[regno * 16];
612 unsigned int exponent;
613 unsigned long fraction[2];
614 int integer;
615
616 integer = raw[7] & 0x80;
617 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
618 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
619 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
1b3f6016 620 | (raw[5] << 8) | raw[4]);
58caa3dc
DJ
621
622 if (exponent == 0x7fff)
623 {
624 /* Special. */
625 return (2);
626 }
627 else if (exponent == 0x0000)
628 {
629 if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
1b3f6016
PA
630 {
631 /* Zero. */
632 return (1);
633 }
58caa3dc 634 else
1b3f6016
PA
635 {
636 /* Special. */
637 return (2);
638 }
58caa3dc
DJ
639 }
640 else
641 {
642 if (integer)
1b3f6016
PA
643 {
644 /* Valid. */
645 return (0);
646 }
58caa3dc 647 else
1b3f6016
PA
648 {
649 /* Special. */
650 return (2);
651 }
58caa3dc
DJ
652 }
653}
654
655void
442ea881 656i387_fxsave_to_cache (struct regcache *regcache, const void *buf)
58caa3dc
DJ
657{
658 struct i387_fxsave *fp = (struct i387_fxsave *) buf;
659 int i, top;
3aee8918
PA
660 int st0_regnum = find_regno (regcache->tdesc, "st0");
661 int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
58caa3dc 662 unsigned long val;
3aee8918
PA
663 /* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
664 int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
58caa3dc
DJ
665
666 for (i = 0; i < 8; i++)
442ea881
PA
667 supply_register (regcache, i + st0_regnum,
668 ((char *) &fp->st_space[0]) + i * 16);
58caa3dc 669 for (i = 0; i < num_xmm_registers; i++)
442ea881
PA
670 supply_register (regcache, i + xmm0_regnum,
671 ((char *) &fp->xmm_space[0]) + i * 16);
58caa3dc 672
442ea881
PA
673 supply_register_by_name (regcache, "fioff", &fp->fioff);
674 supply_register_by_name (regcache, "fooff", &fp->fooff);
675 supply_register_by_name (regcache, "mxcsr", &fp->mxcsr);
1b3f6016 676
58caa3dc
DJ
677 /* Some registers are 16-bit. */
678 val = fp->fctrl & 0xFFFF;
442ea881 679 supply_register_by_name (regcache, "fctrl", &val);
58caa3dc
DJ
680
681 val = fp->fstat & 0xFFFF;
442ea881 682 supply_register_by_name (regcache, "fstat", &val);
58caa3dc
DJ
683
684 /* Generate the form of ftag data that GDB expects. */
685 top = (fp->fstat >> 11) & 0x7;
686 val = 0;
687 for (i = 7; i >= 0; i--)
688 {
689 int tag;
73725ff3 690 if (fp->ftag & (1 << i))
58caa3dc
DJ
691 tag = i387_ftag (fp, (i + 8 - top) % 8);
692 else
693 tag = 3;
694 val |= tag << (2 * i);
695 }
442ea881 696 supply_register_by_name (regcache, "ftag", &val);
58caa3dc
DJ
697
698 val = fp->fiseg & 0xFFFF;
442ea881 699 supply_register_by_name (regcache, "fiseg", &val);
58caa3dc
DJ
700
701 val = fp->foseg & 0xFFFF;
442ea881 702 supply_register_by_name (regcache, "foseg", &val);
58caa3dc
DJ
703
704 val = (fp->fop) & 0x7FF;
442ea881 705 supply_register_by_name (regcache, "fop", &val);
58caa3dc 706}
1570b33e
L
707
708void
709i387_xsave_to_cache (struct regcache *regcache, const void *buf)
710{
711 struct i387_xsave *fp = (struct i387_xsave *) buf;
712 struct i387_fxsave *fxp = (struct i387_fxsave *) buf;
713 int i, top;
714 unsigned long val;
ff6527bb 715 unsigned long long clear_bv;
85724a0e 716 gdb_byte *p;
3aee8918
PA
717 /* Amd64 has 16 xmm regs; I386 has 8 xmm regs. */
718 int num_xmm_registers = register_size (regcache->tdesc, 0) == 8 ? 16 : 8;
1570b33e 719
ff6527bb 720 /* The supported bits in `xstat_bv' are 8 bytes. Clear part in
1570b33e
L
721 vector registers if its bit in xstat_bv is zero. */
722 clear_bv = (~fp->xstate_bv) & x86_xcr0;
723
724 /* Check if any x87 registers are changed. */
df7e5265 725 if ((x86_xcr0 & X86_XSTATE_X87) != 0)
1570b33e 726 {
3aee8918 727 int st0_regnum = find_regno (regcache->tdesc, "st0");
1570b33e 728
df7e5265 729 if ((clear_bv & X86_XSTATE_X87) != 0)
85724a0e
PA
730 {
731 for (i = 0; i < 8; i++)
1c79eb8a 732 supply_register_zeroed (regcache, i + st0_regnum);
85724a0e 733 }
1570b33e 734 else
1570b33e 735 {
85724a0e
PA
736 p = (gdb_byte *) &fp->st_space[0];
737 for (i = 0; i < 8; i++)
738 supply_register (regcache, i + st0_regnum, p + i * 16);
1570b33e
L
739 }
740 }
741
df7e5265 742 if ((x86_xcr0 & X86_XSTATE_SSE) != 0)
1570b33e 743 {
3aee8918 744 int xmm0_regnum = find_regno (regcache->tdesc, "xmm0");
1570b33e 745
df7e5265 746 if ((clear_bv & X86_XSTATE_SSE))
85724a0e
PA
747 {
748 for (i = 0; i < num_xmm_registers; i++)
1c79eb8a 749 supply_register_zeroed (regcache, i + xmm0_regnum);
85724a0e 750 }
1570b33e 751 else
1570b33e 752 {
85724a0e
PA
753 p = (gdb_byte *) &fp->xmm_space[0];
754 for (i = 0; i < num_xmm_registers; i++)
755 supply_register (regcache, i + xmm0_regnum, p + i * 16);
1570b33e
L
756 }
757 }
758
df7e5265 759 if ((x86_xcr0 & X86_XSTATE_AVX) != 0)
1570b33e 760 {
3aee8918 761 int ymm0h_regnum = find_regno (regcache->tdesc, "ymm0h");
1570b33e 762
df7e5265 763 if ((clear_bv & X86_XSTATE_AVX) != 0)
85724a0e
PA
764 {
765 for (i = 0; i < num_xmm_registers; i++)
1c79eb8a 766 supply_register_zeroed (regcache, i + ymm0h_regnum);
85724a0e 767 }
1570b33e 768 else
1570b33e 769 {
85724a0e
PA
770 p = (gdb_byte *) &fp->ymmh_space[0];
771 for (i = 0; i < num_xmm_registers; i++)
772 supply_register (regcache, i + ymm0h_regnum, p + i * 16);
1570b33e
L
773 }
774 }
775
df7e5265 776 if ((x86_xcr0 & X86_XSTATE_BNDREGS))
a196ebeb
WT
777 {
778 int bnd0r_regnum = find_regno (regcache->tdesc, "bnd0raw");
779
780
df7e5265 781 if ((clear_bv & X86_XSTATE_BNDREGS) != 0)
a196ebeb
WT
782 {
783 for (i = 0; i < num_mpx_bnd_registers; i++)
784 supply_register_zeroed (regcache, i + bnd0r_regnum);
785 }
786 else
787 {
788 p = (gdb_byte *) &fp->mpx_bnd_space[0];
789 for (i = 0; i < num_mpx_bnd_registers; i++)
790 supply_register (regcache, i + bnd0r_regnum, p + i * 16);
791 }
792
793 }
794
df7e5265 795 if ((x86_xcr0 & X86_XSTATE_BNDCFG))
a196ebeb
WT
796 {
797 int bndcfg_regnum = find_regno (regcache->tdesc, "bndcfgu");
798
df7e5265 799 if ((clear_bv & X86_XSTATE_BNDCFG) != 0)
a196ebeb
WT
800 {
801 for (i = 0; i < num_mpx_cfg_registers; i++)
802 supply_register_zeroed (regcache, i + bndcfg_regnum);
803 }
804 else
805 {
806 p = (gdb_byte *) &fp->mpx_cfg_space[0];
807 for (i = 0; i < num_mpx_cfg_registers; i++)
808 supply_register (regcache, i + bndcfg_regnum, p + i * 8);
809 }
810 }
811
df7e5265 812 if ((x86_xcr0 & X86_XSTATE_K) != 0)
01f9f808
MS
813 {
814 int k0_regnum = find_regno (regcache->tdesc, "k0");
815
df7e5265 816 if ((clear_bv & X86_XSTATE_K) != 0)
01f9f808
MS
817 {
818 for (i = 0; i < num_avx512_k_registers; i++)
819 supply_register_zeroed (regcache, i + k0_regnum);
820 }
821 else
822 {
823 p = (gdb_byte *) &fp->k_space[0];
824 for (i = 0; i < num_avx512_k_registers; i++)
825 supply_register (regcache, i + k0_regnum, p + i * 8);
826 }
827 }
828
df7e5265 829 if ((x86_xcr0 & X86_XSTATE_ZMM_H) != 0)
01f9f808
MS
830 {
831 int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h");
832
df7e5265 833 if ((clear_bv & X86_XSTATE_ZMM_H) != 0)
01f9f808
MS
834 {
835 for (i = 0; i < num_avx512_zmmh_low_registers; i++)
836 supply_register_zeroed (regcache, i + zmm0h_regnum);
837 }
838 else
839 {
840 p = (gdb_byte *) &fp->zmmh_low_space[0];
841 for (i = 0; i < num_avx512_zmmh_low_registers; i++)
842 supply_register (regcache, i + zmm0h_regnum, p + i * 32);
843 }
844 }
845
df7e5265 846 if ((x86_xcr0 & X86_XSTATE_ZMM) != 0)
01f9f808
MS
847 {
848 int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
849 int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
850 int xmm16_regnum = find_regno (regcache->tdesc, "xmm16");
851
df7e5265 852 if ((clear_bv & X86_XSTATE_ZMM) != 0)
01f9f808
MS
853 {
854 for (i = 0; i < num_avx512_zmmh_high_registers; i++)
855 supply_register_zeroed (regcache, i + zmm16h_regnum);
856 for (i = 0; i < num_avx512_ymmh_registers; i++)
857 supply_register_zeroed (regcache, i + ymm16h_regnum);
858 for (i = 0; i < num_avx512_xmm_registers; i++)
859 supply_register_zeroed (regcache, i + xmm16_regnum);
860 }
861 else
862 {
863 p = (gdb_byte *) &fp->zmmh_high_space[0];
864 for (i = 0; i < num_avx512_zmmh_high_registers; i++)
865 supply_register (regcache, i + zmm16h_regnum, p + 32 + i * 64);
866 for (i = 0; i < num_avx512_ymmh_registers; i++)
867 supply_register (regcache, i + ymm16h_regnum, p + 16 + i * 64);
868 for (i = 0; i < num_avx512_xmm_registers; i++)
869 supply_register (regcache, i + xmm16_regnum, p + i * 64);
870 }
871 }
872
51547df6
MS
873 if ((x86_xcr0 & X86_XSTATE_PKRU) != 0)
874 {
875 int pkru_regnum = find_regno (regcache->tdesc, "pkru");
876
877 if ((clear_bv & X86_XSTATE_PKRU) != 0)
878 {
879 for (i = 0; i < num_pkeys_registers; i++)
880 supply_register_zeroed (regcache, i + pkru_regnum);
881 }
882 else
883 {
884 p = (gdb_byte *) &fp->pkru_space[0];
885 for (i = 0; i < num_pkeys_registers; i++)
886 supply_register (regcache, i + pkru_regnum, p + i * 4);
887 }
888 }
889
8ee22052
AB
890 if ((clear_bv & (X86_XSTATE_SSE | X86_XSTATE_AVX))
891 == (X86_XSTATE_SSE | X86_XSTATE_AVX))
892 {
893 unsigned int default_mxcsr = I387_MXCSR_INIT_VAL;
894 supply_register_by_name (regcache, "mxcsr", &default_mxcsr);
895 }
896 else
897 supply_register_by_name (regcache, "mxcsr", &fp->mxcsr);
1570b33e 898
8ee22052
AB
899 if ((clear_bv & X86_XSTATE_X87) != 0)
900 {
901 supply_register_by_name_zeroed (regcache, "fioff");
902 supply_register_by_name_zeroed (regcache, "fooff");
1570b33e 903
8ee22052
AB
904 val = I387_FCTRL_INIT_VAL;
905 supply_register_by_name (regcache, "fctrl", &val);
1570b33e 906
8ee22052
AB
907 supply_register_by_name_zeroed (regcache, "fstat");
908
909 val = 0xFFFF;
910 supply_register_by_name (regcache, "ftag", &val);
911
912 supply_register_by_name_zeroed (regcache, "fiseg");
913 supply_register_by_name_zeroed (regcache, "foseg");
914 supply_register_by_name_zeroed (regcache, "fop");
1570b33e 915 }
8ee22052
AB
916 else
917 {
918 supply_register_by_name (regcache, "fioff", &fp->fioff);
919 supply_register_by_name (regcache, "fooff", &fp->fooff);
1570b33e 920
8ee22052
AB
921 /* Some registers are 16-bit. */
922 val = fp->fctrl & 0xFFFF;
923 supply_register_by_name (regcache, "fctrl", &val);
1570b33e 924
8ee22052
AB
925 val = fp->fstat & 0xFFFF;
926 supply_register_by_name (regcache, "fstat", &val);
1570b33e 927
8ee22052
AB
928 /* Generate the form of ftag data that GDB expects. */
929 top = (fp->fstat >> 11) & 0x7;
930 val = 0;
931 for (i = 7; i >= 0; i--)
932 {
933 int tag;
934 if (fp->ftag & (1 << i))
935 tag = i387_ftag (fxp, (i + 8 - top) % 8);
936 else
937 tag = 3;
938 val |= tag << (2 * i);
939 }
940 supply_register_by_name (regcache, "ftag", &val);
941
942 val = fp->fiseg & 0xFFFF;
943 supply_register_by_name (regcache, "fiseg", &val);
944
945 val = fp->foseg & 0xFFFF;
946 supply_register_by_name (regcache, "foseg", &val);
947
948 val = (fp->fop) & 0x7FF;
949 supply_register_by_name (regcache, "fop", &val);
950 }
1570b33e
L
951}
952
953/* Default to SSE. */
df7e5265 954unsigned long long x86_xcr0 = X86_XSTATE_SSE_MASK;
This page took 1.435661 seconds and 4 git commands to generate.