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