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 7 #include "cpu.h" 8 9 void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf) 10 { 11 CPUX86State *env = &cpu->env; 12 X86XSaveArea *xsave = buf; 13 14 uint16_t cwd, swd, twd; 15 int i; 16 memset(xsave, 0, sizeof(X86XSaveArea)); 17 twd = 0; 18 swd = env->fpus & ~(7 << 11); 19 swd |= (env->fpstt & 7) << 11; 20 cwd = env->fpuc; 21 for (i = 0; i < 8; ++i) { 22 twd |= (!env->fptags[i]) << i; 23 } 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, 31 sizeof 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); 39 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)); 52 } 53 54 #ifdef TARGET_X86_64 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); 58 #endif 59 60 } 61 62 void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf) 63 { 64 65 CPUX86State *env = &cpu->env; 66 const X86XSaveArea *xsave = buf; 67 68 int i; 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; 75 env->fpus = swd; 76 env->fpuc = cwd; 77 for (i = 0; i < 8; ++i) { 78 env->fptags[i] = !((twd >> i) & 1); 79 } 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, 84 sizeof env->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); 91 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); 104 } 105 106 #ifdef TARGET_X86_64 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); 110 #endif 111 112 } 113