target/i386: implement XSAVE and XRSTOR of AVX registers
Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
f8d19eec0d
commit
892544317f
@ -2559,6 +2559,22 @@ static void do_xsave_sse(CPUX86State *env, target_ulong ptr, uintptr_t ra)
|
||||
}
|
||||
}
|
||||
|
||||
static void do_xsave_ymmh(CPUX86State *env, target_ulong ptr, uintptr_t ra)
|
||||
{
|
||||
int i, nb_xmm_regs;
|
||||
|
||||
if (env->hflags & HF_CS64_MASK) {
|
||||
nb_xmm_regs = 16;
|
||||
} else {
|
||||
nb_xmm_regs = 8;
|
||||
}
|
||||
|
||||
for (i = 0; i < nb_xmm_regs; i++, ptr += 16) {
|
||||
cpu_stq_data_ra(env, ptr, env->xmm_regs[i].ZMM_Q(2), ra);
|
||||
cpu_stq_data_ra(env, ptr + 8, env->xmm_regs[i].ZMM_Q(3), ra);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_xsave_bndregs(CPUX86State *env, target_ulong ptr, uintptr_t ra)
|
||||
{
|
||||
target_ulong addr = ptr + offsetof(XSaveBNDREG, bnd_regs);
|
||||
@ -2651,6 +2667,9 @@ static void do_xsave(CPUX86State *env, target_ulong ptr, uint64_t rfbm,
|
||||
if (opt & XSTATE_SSE_MASK) {
|
||||
do_xsave_sse(env, ptr, ra);
|
||||
}
|
||||
if (opt & XSTATE_YMM_MASK) {
|
||||
do_xsave_ymmh(env, ptr + XO(avx_state), ra);
|
||||
}
|
||||
if (opt & XSTATE_BNDREGS_MASK) {
|
||||
do_xsave_bndregs(env, ptr + XO(bndreg_state), ra);
|
||||
}
|
||||
@ -2725,6 +2744,54 @@ static void do_xrstor_sse(CPUX86State *env, target_ulong ptr, uintptr_t ra)
|
||||
}
|
||||
}
|
||||
|
||||
static void do_clear_sse(CPUX86State *env)
|
||||
{
|
||||
int i, nb_xmm_regs;
|
||||
|
||||
if (env->hflags & HF_CS64_MASK) {
|
||||
nb_xmm_regs = 16;
|
||||
} else {
|
||||
nb_xmm_regs = 8;
|
||||
}
|
||||
|
||||
for (i = 0; i < nb_xmm_regs; i++) {
|
||||
env->xmm_regs[i].ZMM_Q(0) = 0;
|
||||
env->xmm_regs[i].ZMM_Q(1) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_xrstor_ymmh(CPUX86State *env, target_ulong ptr, uintptr_t ra)
|
||||
{
|
||||
int i, nb_xmm_regs;
|
||||
|
||||
if (env->hflags & HF_CS64_MASK) {
|
||||
nb_xmm_regs = 16;
|
||||
} else {
|
||||
nb_xmm_regs = 8;
|
||||
}
|
||||
|
||||
for (i = 0; i < nb_xmm_regs; i++, ptr += 16) {
|
||||
env->xmm_regs[i].ZMM_Q(2) = cpu_ldq_data_ra(env, ptr, ra);
|
||||
env->xmm_regs[i].ZMM_Q(3) = cpu_ldq_data_ra(env, ptr + 8, ra);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_clear_ymmh(CPUX86State *env)
|
||||
{
|
||||
int i, nb_xmm_regs;
|
||||
|
||||
if (env->hflags & HF_CS64_MASK) {
|
||||
nb_xmm_regs = 16;
|
||||
} else {
|
||||
nb_xmm_regs = 8;
|
||||
}
|
||||
|
||||
for (i = 0; i < nb_xmm_regs; i++) {
|
||||
env->xmm_regs[i].ZMM_Q(2) = 0;
|
||||
env->xmm_regs[i].ZMM_Q(3) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_xrstor_bndregs(CPUX86State *env, target_ulong ptr, uintptr_t ra)
|
||||
{
|
||||
target_ulong addr = ptr + offsetof(XSaveBNDREG, bnd_regs);
|
||||
@ -2831,9 +2898,14 @@ static void do_xrstor(CPUX86State *env, target_ulong ptr, uint64_t rfbm, uintptr
|
||||
if (xstate_bv & XSTATE_SSE_MASK) {
|
||||
do_xrstor_sse(env, ptr, ra);
|
||||
} else {
|
||||
/* ??? When AVX is implemented, we may have to be more
|
||||
selective in the clearing. */
|
||||
memset(env->xmm_regs, 0, sizeof(env->xmm_regs));
|
||||
do_clear_sse(env);
|
||||
}
|
||||
}
|
||||
if (rfbm & XSTATE_YMM_MASK) {
|
||||
if (xstate_bv & XSTATE_YMM_MASK) {
|
||||
do_xrstor_ymmh(env, ptr + XO(avx_state), ra);
|
||||
} else {
|
||||
do_clear_ymmh(env);
|
||||
}
|
||||
}
|
||||
if (rfbm & XSTATE_BNDREGS_MASK) {
|
||||
|
Loading…
Reference in New Issue
Block a user