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"
6 #include "qapi/error.h"
8 #include "qemu-common.h"
11 void x86_cpu_xsave_all_areas(X86CPU
*cpu
, X86XSaveArea
*buf
)
13 CPUX86State
*env
= &cpu
->env
;
14 X86XSaveArea
*xsave
= buf
;
16 uint16_t cwd
, swd
, twd
;
18 memset(xsave
, 0, sizeof(X86XSaveArea
));
20 swd
= env
->fpus
& ~(7 << 11);
21 swd
|= (env
->fpstt
& 7) << 11;
23 for (i
= 0; i
< 8; ++i
) {
24 twd
|= (!env
->fptags
[i
]) << i
;
26 xsave
->legacy
.fcw
= cwd
;
27 xsave
->legacy
.fsw
= swd
;
28 xsave
->legacy
.ftw
= twd
;
29 xsave
->legacy
.fpop
= env
->fpop
;
30 xsave
->legacy
.fpip
= env
->fpip
;
31 xsave
->legacy
.fpdp
= env
->fpdp
;
32 memcpy(&xsave
->legacy
.fpregs
, env
->fpregs
,
34 xsave
->legacy
.mxcsr
= env
->mxcsr
;
35 xsave
->header
.xstate_bv
= env
->xstate_bv
;
36 memcpy(&xsave
->bndreg_state
.bnd_regs
, env
->bnd_regs
,
37 sizeof env
->bnd_regs
);
38 xsave
->bndcsr_state
.bndcsr
= env
->bndcs_regs
;
39 memcpy(&xsave
->opmask_state
.opmask_regs
, env
->opmask_regs
,
40 sizeof env
->opmask_regs
);
42 for (i
= 0; i
< CPU_NB_REGS
; i
++) {
43 uint8_t *xmm
= xsave
->legacy
.xmm_regs
[i
];
44 uint8_t *ymmh
= xsave
->avx_state
.ymmh
[i
];
45 uint8_t *zmmh
= xsave
->zmm_hi256_state
.zmm_hi256
[i
];
46 stq_p(xmm
, env
->xmm_regs
[i
].ZMM_Q(0));
47 stq_p(xmm
+8, env
->xmm_regs
[i
].ZMM_Q(1));
48 stq_p(ymmh
, env
->xmm_regs
[i
].ZMM_Q(2));
49 stq_p(ymmh
+8, env
->xmm_regs
[i
].ZMM_Q(3));
50 stq_p(zmmh
, env
->xmm_regs
[i
].ZMM_Q(4));
51 stq_p(zmmh
+8, env
->xmm_regs
[i
].ZMM_Q(5));
52 stq_p(zmmh
+16, env
->xmm_regs
[i
].ZMM_Q(6));
53 stq_p(zmmh
+24, env
->xmm_regs
[i
].ZMM_Q(7));
57 memcpy(&xsave
->hi16_zmm_state
.hi16_zmm
, &env
->xmm_regs
[16],
58 16 * sizeof env
->xmm_regs
[16]);
59 memcpy(&xsave
->pkru_state
, &env
->pkru
, sizeof env
->pkru
);
64 void x86_cpu_xrstor_all_areas(X86CPU
*cpu
, const X86XSaveArea
*buf
)
67 CPUX86State
*env
= &cpu
->env
;
68 const X86XSaveArea
*xsave
= buf
;
71 uint16_t cwd
, swd
, twd
;
72 cwd
= xsave
->legacy
.fcw
;
73 swd
= xsave
->legacy
.fsw
;
74 twd
= xsave
->legacy
.ftw
;
75 env
->fpop
= xsave
->legacy
.fpop
;
76 env
->fpstt
= (swd
>> 11) & 7;
79 for (i
= 0; i
< 8; ++i
) {
80 env
->fptags
[i
] = !((twd
>> i
) & 1);
82 env
->fpip
= xsave
->legacy
.fpip
;
83 env
->fpdp
= xsave
->legacy
.fpdp
;
84 env
->mxcsr
= xsave
->legacy
.mxcsr
;
85 memcpy(env
->fpregs
, &xsave
->legacy
.fpregs
,
87 env
->xstate_bv
= xsave
->header
.xstate_bv
;
88 memcpy(env
->bnd_regs
, &xsave
->bndreg_state
.bnd_regs
,
89 sizeof env
->bnd_regs
);
90 env
->bndcs_regs
= xsave
->bndcsr_state
.bndcsr
;
91 memcpy(env
->opmask_regs
, &xsave
->opmask_state
.opmask_regs
,
92 sizeof env
->opmask_regs
);
94 for (i
= 0; i
< CPU_NB_REGS
; i
++) {
95 const uint8_t *xmm
= xsave
->legacy
.xmm_regs
[i
];
96 const uint8_t *ymmh
= xsave
->avx_state
.ymmh
[i
];
97 const uint8_t *zmmh
= xsave
->zmm_hi256_state
.zmm_hi256
[i
];
98 env
->xmm_regs
[i
].ZMM_Q(0) = ldq_p(xmm
);
99 env
->xmm_regs
[i
].ZMM_Q(1) = ldq_p(xmm
+8);
100 env
->xmm_regs
[i
].ZMM_Q(2) = ldq_p(ymmh
);
101 env
->xmm_regs
[i
].ZMM_Q(3) = ldq_p(ymmh
+8);
102 env
->xmm_regs
[i
].ZMM_Q(4) = ldq_p(zmmh
);
103 env
->xmm_regs
[i
].ZMM_Q(5) = ldq_p(zmmh
+8);
104 env
->xmm_regs
[i
].ZMM_Q(6) = ldq_p(zmmh
+16);
105 env
->xmm_regs
[i
].ZMM_Q(7) = ldq_p(zmmh
+24);
109 memcpy(&env
->xmm_regs
[16], &xsave
->hi16_zmm_state
.hi16_zmm
,
110 16 * sizeof env
->xmm_regs
[16]);
111 memcpy(&env
->pkru
, &xsave
->pkru_state
, sizeof env
->pkru
);