Commit | Line | Data |
---|---|---|
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 |
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"); |
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 | ||
173 | void | |
442ea881 | 174 | i387_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 | ||
209 | void | |
442ea881 | 210 | i387_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 |
255 | void |
256 | i387_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 |
608 | static int |
609 | i387_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 | ||
655 | void | |
442ea881 | 656 | i387_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 | |
708 | void | |
709 | i387_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 | 954 | unsigned long long x86_xcr0 = X86_XSTATE_SSE_MASK; |