[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 32/37] target/i386: implement XSAVE and XRSTOR of AVX register
From: |
Paolo Bonzini |
Subject: |
[PATCH v2 32/37] target/i386: implement XSAVE and XRSTOR of AVX registers |
Date: |
Tue, 20 Sep 2022 19:25:02 +0200 |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/fpu_helper.c | 78 ++++++++++++++++++++++++++++++++++--
1 file changed, 75 insertions(+), 3 deletions(-)
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
index 819e920ec6..c1e3d74c84 100644
--- a/target/i386/tcg/fpu_helper.c
+++ b/target/i386/tcg/fpu_helper.c
@@ -2571,6 +2571,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);
@@ -2663,6 +2679,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);
}
@@ -2737,6 +2756,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);
@@ -2856,9 +2923,14 @@ void helper_xrstor(CPUX86State *env, target_ulong ptr,
uint64_t rfbm)
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) {
--
2.37.2
- [PATCH v2 21/37] target/i386: reimplement 0x0f 0x50-0x5f, add AVX, (continued)
- [PATCH v2 21/37] target/i386: reimplement 0x0f 0x50-0x5f, add AVX, Paolo Bonzini, 2022/09/20
- [PATCH v2 26/37] target/i386: reimplement 0x0f 0x3a, add AVX, Paolo Bonzini, 2022/09/20
- [PATCH v2 24/37] target/i386: reimplement 0x0f 0xd0-0xd7, 0xe0-0xe7, 0xf0-0xf7, add AVX, Paolo Bonzini, 2022/09/20
- [PATCH v2 36/37] target/i386: move 3DNow to the new decoder, Paolo Bonzini, 2022/09/20
- [PATCH v2 35/37] tests/tcg: extend SSE tests to AVX, Paolo Bonzini, 2022/09/20
- [PATCH v2 32/37] target/i386: implement XSAVE and XRSTOR of AVX registers,
Paolo Bonzini <=