qemu/target/i386/xsave_helper.c
<<
>>
Prefs
   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 "qemu-common.h"
   8#include "cpu.h"
   9
  10void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf)
  11{
  12    CPUX86State *env = &cpu->env;
  13    X86XSaveArea *xsave = buf;
  14
  15    uint16_t cwd, swd, twd;
  16    int i;
  17    memset(xsave, 0, sizeof(X86XSaveArea));
  18    twd = 0;
  19    swd = env->fpus & ~(7 << 11);
  20    swd |= (env->fpstt & 7) << 11;
  21    cwd = env->fpuc;
  22    for (i = 0; i < 8; ++i) {
  23        twd |= (!env->fptags[i]) << i;
  24    }
  25    xsave->legacy.fcw = cwd;
  26    xsave->legacy.fsw = swd;
  27    xsave->legacy.ftw = twd;
  28    xsave->legacy.fpop = env->fpop;
  29    xsave->legacy.fpip = env->fpip;
  30    xsave->legacy.fpdp = env->fpdp;
  31    memcpy(&xsave->legacy.fpregs, env->fpregs,
  32            sizeof env->fpregs);
  33    xsave->legacy.mxcsr = env->mxcsr;
  34    xsave->header.xstate_bv = env->xstate_bv;
  35    memcpy(&xsave->bndreg_state.bnd_regs, env->bnd_regs,
  36            sizeof env->bnd_regs);
  37    xsave->bndcsr_state.bndcsr = env->bndcs_regs;
  38    memcpy(&xsave->opmask_state.opmask_regs, env->opmask_regs,
  39            sizeof env->opmask_regs);
  40
  41    for (i = 0; i < CPU_NB_REGS; i++) {
  42        uint8_t *xmm = xsave->legacy.xmm_regs[i];
  43        uint8_t *ymmh = xsave->avx_state.ymmh[i];
  44        uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i];
  45        stq_p(xmm,     env->xmm_regs[i].ZMM_Q(0));
  46        stq_p(xmm+8,   env->xmm_regs[i].ZMM_Q(1));
  47        stq_p(ymmh,    env->xmm_regs[i].ZMM_Q(2));
  48        stq_p(ymmh+8,  env->xmm_regs[i].ZMM_Q(3));
  49        stq_p(zmmh,    env->xmm_regs[i].ZMM_Q(4));
  50        stq_p(zmmh+8,  env->xmm_regs[i].ZMM_Q(5));
  51        stq_p(zmmh+16, env->xmm_regs[i].ZMM_Q(6));
  52        stq_p(zmmh+24, env->xmm_regs[i].ZMM_Q(7));
  53    }
  54
  55#ifdef TARGET_X86_64
  56    memcpy(&xsave->hi16_zmm_state.hi16_zmm, &env->xmm_regs[16],
  57            16 * sizeof env->xmm_regs[16]);
  58    memcpy(&xsave->pkru_state, &env->pkru, sizeof env->pkru);
  59#endif
  60
  61}
  62
  63void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf)
  64{
  65
  66    CPUX86State *env = &cpu->env;
  67    const X86XSaveArea *xsave = buf;
  68
  69    int i;
  70    uint16_t cwd, swd, twd;
  71    cwd = xsave->legacy.fcw;
  72    swd = xsave->legacy.fsw;
  73    twd = xsave->legacy.ftw;
  74    env->fpop = xsave->legacy.fpop;
  75    env->fpstt = (swd >> 11) & 7;
  76    env->fpus = swd;
  77    env->fpuc = cwd;
  78    for (i = 0; i < 8; ++i) {
  79        env->fptags[i] = !((twd >> i) & 1);
  80    }
  81    env->fpip = xsave->legacy.fpip;
  82    env->fpdp = xsave->legacy.fpdp;
  83    env->mxcsr = xsave->legacy.mxcsr;
  84    memcpy(env->fpregs, &xsave->legacy.fpregs,
  85            sizeof env->fpregs);
  86    env->xstate_bv = xsave->header.xstate_bv;
  87    memcpy(env->bnd_regs, &xsave->bndreg_state.bnd_regs,
  88            sizeof env->bnd_regs);
  89    env->bndcs_regs = xsave->bndcsr_state.bndcsr;
  90    memcpy(env->opmask_regs, &xsave->opmask_state.opmask_regs,
  91            sizeof env->opmask_regs);
  92
  93    for (i = 0; i < CPU_NB_REGS; i++) {
  94        const uint8_t *xmm = xsave->legacy.xmm_regs[i];
  95        const uint8_t *ymmh = xsave->avx_state.ymmh[i];
  96        const uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i];
  97        env->xmm_regs[i].ZMM_Q(0) = ldq_p(xmm);
  98        env->xmm_regs[i].ZMM_Q(1) = ldq_p(xmm+8);
  99        env->xmm_regs[i].ZMM_Q(2) = ldq_p(ymmh);
 100        env->xmm_regs[i].ZMM_Q(3) = ldq_p(ymmh+8);
 101        env->xmm_regs[i].ZMM_Q(4) = ldq_p(zmmh);
 102        env->xmm_regs[i].ZMM_Q(5) = ldq_p(zmmh+8);
 103        env->xmm_regs[i].ZMM_Q(6) = ldq_p(zmmh+16);
 104        env->xmm_regs[i].ZMM_Q(7) = ldq_p(zmmh+24);
 105    }
 106
 107#ifdef TARGET_X86_64
 108    memcpy(&env->xmm_regs[16], &xsave->hi16_zmm_state.hi16_zmm,
 109           16 * sizeof env->xmm_regs[16]);
 110    memcpy(&env->pkru, &xsave->pkru_state, sizeof env->pkru);
 111#endif
 112
 113}
 114