2 * This work is licensed under the terms of the GNU GPL, version 2 or later.
3 * See the COPYING file in the top-level directory.
5 #include "qemu/osdep.h"
9 void x86_cpu_xsave_all_areas(X86CPU
*cpu
, X86XSaveArea
*buf
)
11 CPUX86State
*env
= &cpu
->env
;
12 X86XSaveArea
*xsave
= buf
;
14 uint16_t cwd
, swd
, twd
;
16 memset(xsave
, 0, sizeof(X86XSaveArea
));
18 swd
= env
->fpus
& ~(7 << 11);
19 swd
|= (env
->fpstt
& 7) << 11;
21 for (i
= 0; i
< 8; ++i
) {
22 twd
|= (!env
->fptags
[i
]) << i
;
24 xsave
->legacy
.fcw
= cwd
;
25 xsave
->legacy
.fsw
= swd
;
26 xsave
->legacy
.ftw
= twd
;
27 xsave
->legacy
.fpop
= env
->fpop
;
28 xsave
->legacy
.fpip
= env
->fpip
;
29 xsave
->legacy
.fpdp
= env
->fpdp
;
30 memcpy(&xsave
->legacy
.fpregs
, env
->fpregs
,
32 xsave
->legacy
.mxcsr
= env
->mxcsr
;
33 xsave
->header
.xstate_bv
= env
->xstate_bv
;
34 memcpy(&xsave
->bndreg_state
.bnd_regs
, env
->bnd_regs
,
35 sizeof env
->bnd_regs
);
36 xsave
->bndcsr_state
.bndcsr
= env
->bndcs_regs
;
37 memcpy(&xsave
->opmask_state
.opmask_regs
, env
->opmask_regs
,
38 sizeof env
->opmask_regs
);
40 for (i
= 0; i
< CPU_NB_REGS
; i
++) {
41 uint8_t *xmm
= xsave
->legacy
.xmm_regs
[i
];
42 uint8_t *ymmh
= xsave
->avx_state
.ymmh
[i
];
43 uint8_t *zmmh
= xsave
->zmm_hi256_state
.zmm_hi256
[i
];
44 stq_p(xmm
, env
->xmm_regs
[i
].ZMM_Q(0));
45 stq_p(xmm
+8, env
->xmm_regs
[i
].ZMM_Q(1));
46 stq_p(ymmh
, env
->xmm_regs
[i
].ZMM_Q(2));
47 stq_p(ymmh
+8, env
->xmm_regs
[i
].ZMM_Q(3));
48 stq_p(zmmh
, env
->xmm_regs
[i
].ZMM_Q(4));
49 stq_p(zmmh
+8, env
->xmm_regs
[i
].ZMM_Q(5));
50 stq_p(zmmh
+16, env
->xmm_regs
[i
].ZMM_Q(6));
51 stq_p(zmmh
+24, env
->xmm_regs
[i
].ZMM_Q(7));
55 memcpy(&xsave
->hi16_zmm_state
.hi16_zmm
, &env
->xmm_regs
[16],
56 16 * sizeof env
->xmm_regs
[16]);
57 memcpy(&xsave
->pkru_state
, &env
->pkru
, sizeof env
->pkru
);
62 void x86_cpu_xrstor_all_areas(X86CPU
*cpu
, const X86XSaveArea
*buf
)
65 CPUX86State
*env
= &cpu
->env
;
66 const X86XSaveArea
*xsave
= buf
;
69 uint16_t cwd
, swd
, twd
;
70 cwd
= xsave
->legacy
.fcw
;
71 swd
= xsave
->legacy
.fsw
;
72 twd
= xsave
->legacy
.ftw
;
73 env
->fpop
= xsave
->legacy
.fpop
;
74 env
->fpstt
= (swd
>> 11) & 7;
77 for (i
= 0; i
< 8; ++i
) {
78 env
->fptags
[i
] = !((twd
>> i
) & 1);
80 env
->fpip
= xsave
->legacy
.fpip
;
81 env
->fpdp
= xsave
->legacy
.fpdp
;
82 env
->mxcsr
= xsave
->legacy
.mxcsr
;
83 memcpy(env
->fpregs
, &xsave
->legacy
.fpregs
,
85 env
->xstate_bv
= xsave
->header
.xstate_bv
;
86 memcpy(env
->bnd_regs
, &xsave
->bndreg_state
.bnd_regs
,
87 sizeof env
->bnd_regs
);
88 env
->bndcs_regs
= xsave
->bndcsr_state
.bndcsr
;
89 memcpy(env
->opmask_regs
, &xsave
->opmask_state
.opmask_regs
,
90 sizeof env
->opmask_regs
);
92 for (i
= 0; i
< CPU_NB_REGS
; i
++) {
93 const uint8_t *xmm
= xsave
->legacy
.xmm_regs
[i
];
94 const uint8_t *ymmh
= xsave
->avx_state
.ymmh
[i
];
95 const uint8_t *zmmh
= xsave
->zmm_hi256_state
.zmm_hi256
[i
];
96 env
->xmm_regs
[i
].ZMM_Q(0) = ldq_p(xmm
);
97 env
->xmm_regs
[i
].ZMM_Q(1) = ldq_p(xmm
+8);
98 env
->xmm_regs
[i
].ZMM_Q(2) = ldq_p(ymmh
);
99 env
->xmm_regs
[i
].ZMM_Q(3) = ldq_p(ymmh
+8);
100 env
->xmm_regs
[i
].ZMM_Q(4) = ldq_p(zmmh
);
101 env
->xmm_regs
[i
].ZMM_Q(5) = ldq_p(zmmh
+8);
102 env
->xmm_regs
[i
].ZMM_Q(6) = ldq_p(zmmh
+16);
103 env
->xmm_regs
[i
].ZMM_Q(7) = ldq_p(zmmh
+24);
107 memcpy(&env
->xmm_regs
[16], &xsave
->hi16_zmm_state
.hi16_zmm
,
108 16 * sizeof env
->xmm_regs
[16]);
109 memcpy(&env
->pkru
, &xsave
->pkru_state
, sizeof env
->pkru
);