xref: /qemu/target/i386/xsave_helper.c (revision 6402cbbb)
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 }
115