]>
Commit | Line | Data |
---|---|---|
86a57621 SAGDR |
1 | /* |
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. | |
4 | */ | |
5 | #include "qemu/osdep.h" | |
6 | #include "qapi/error.h" | |
7 | ||
8 | #include "qemu-common.h" | |
9 | #include "cpu.h" | |
10 | ||
11 | void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf) | |
12 | { | |
13 | CPUX86State *env = &cpu->env; | |
14 | X86XSaveArea *xsave = buf; | |
15 | ||
16 | uint16_t cwd, swd, twd; | |
17 | int i; | |
18 | memset(xsave, 0, sizeof(X86XSaveArea)); | |
19 | twd = 0; | |
20 | swd = env->fpus & ~(7 << 11); | |
21 | swd |= (env->fpstt & 7) << 11; | |
22 | cwd = env->fpuc; | |
23 | for (i = 0; i < 8; ++i) { | |
24 | twd |= (!env->fptags[i]) << i; | |
25 | } | |
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, | |
33 | sizeof 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); | |
41 | ||
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)); | |
54 | } | |
55 | ||
56 | #ifdef TARGET_X86_64 | |
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); | |
60 | #endif | |
61 | ||
62 | } | |
63 | ||
64 | void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf) | |
65 | { | |
66 | ||
67 | CPUX86State *env = &cpu->env; | |
68 | const X86XSaveArea *xsave = buf; | |
69 | ||
70 | int i; | |
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; | |
77 | env->fpus = swd; | |
78 | env->fpuc = cwd; | |
79 | for (i = 0; i < 8; ++i) { | |
80 | env->fptags[i] = !((twd >> i) & 1); | |
81 | } | |
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, | |
86 | sizeof env->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); | |
93 | ||
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); | |
106 | } | |
107 | ||
108 | #ifdef TARGET_X86_64 | |
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); | |
112 | #endif | |
113 | ||
114 | } |