From patchwork Tue Feb 9 17:13:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 8264051 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A612ABEEE5 for ; Tue, 9 Feb 2016 17:13:39 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B78A720254 for ; Tue, 9 Feb 2016 17:13:38 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9F5512022D for ; Tue, 9 Feb 2016 17:13:37 +0000 (UTC) Received: from localhost ([::1]:58475 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTBr6-0007ZG-UI for patchwork-qemu-devel@patchwork.kernel.org; Tue, 09 Feb 2016 12:13:36 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46239) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTBqq-0007Uw-1i for qemu-devel@nongnu.org; Tue, 09 Feb 2016 12:13:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aTBqn-0007Hb-To for qemu-devel@nongnu.org; Tue, 09 Feb 2016 12:13:19 -0500 Received: from mx1.redhat.com ([209.132.183.28]:45166) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTBqn-0007HV-KH for qemu-devel@nongnu.org; Tue, 09 Feb 2016 12:13:17 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (Postfix) with ESMTPS id 37517C60EF; Tue, 9 Feb 2016 17:13:17 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-112-25.ams2.redhat.com [10.36.112.25]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u19HDDHC024623; Tue, 9 Feb 2016 12:13:15 -0500 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 9 Feb 2016 18:13:09 +0100 Message-Id: <1455037993-25461-2-git-send-email-pbonzini@redhat.com> In-Reply-To: <1455037993-25461-1-git-send-email-pbonzini@redhat.com> References: <1455037993-25461-1-git-send-email-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: rth@twiddle.net Subject: [Qemu-devel] [PATCH 1/5] target-i386: Split fxsave/fxrstor implementation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Richard Henderson We will be able to reuse these pieces for XSAVE/XRSTOR. Signed-off-by: Richard Henderson Message-Id: <1436429849-18052-2-git-send-email-rth@twiddle.net> Signed-off-by: Paolo Bonzini --- target-i386/fpu_helper.c | 160 ++++++++++++++++++++++++++--------------------- target-i386/helper.h | 4 +- target-i386/translate.c | 4 +- 3 files changed, 92 insertions(+), 76 deletions(-) diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c index 2d54b47..dc16023 100644 --- a/target-i386/fpu_helper.c +++ b/target-i386/fpu_helper.c @@ -1115,18 +1115,11 @@ void cpu_x86_frstor(CPUX86State *env, target_ulong ptr, int data32) } #endif -static void do_fxsave(CPUX86State *env, target_ulong ptr, int data64, - uintptr_t retaddr) +static void do_xsave_fpu(CPUX86State *env, target_ulong ptr, uintptr_t retaddr) { - int fpus, fptag, i, nb_xmm_regs; - floatx80 tmp; + int fpus, fptag, i; target_ulong addr; - /* The operand must be 16 byte aligned */ - if (ptr & 0xf) { - raise_exception_ra(env, EXCP0D_GPF, retaddr); - } - fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; fptag = 0; for (i = 0; i < 8; i++) { @@ -1135,66 +1128,72 @@ static void do_fxsave(CPUX86State *env, target_ulong ptr, int data64, cpu_stw_data_ra(env, ptr, env->fpuc, retaddr); cpu_stw_data_ra(env, ptr + 2, fpus, retaddr); cpu_stw_data_ra(env, ptr + 4, fptag ^ 0xff, retaddr); -#ifdef TARGET_X86_64 - if (data64) { - cpu_stq_data_ra(env, ptr + 0x08, 0, retaddr); /* rip */ - cpu_stq_data_ra(env, ptr + 0x10, 0, retaddr); /* rdp */ - } else -#endif - { - cpu_stl_data_ra(env, ptr + 0x08, 0, retaddr); /* eip */ - cpu_stl_data_ra(env, ptr + 0x0c, 0, retaddr); /* sel */ - cpu_stl_data_ra(env, ptr + 0x10, 0, retaddr); /* dp */ - cpu_stl_data_ra(env, ptr + 0x14, 0, retaddr); /* sel */ - } + + /* In 32-bit mode this is eip, sel, dp, sel. + * In 64-bit mode this is rip, rdp. + * But in either case we don't write actual data, just zeros. + */ + cpu_stq_data_ra(env, ptr + 0x08, 0, retaddr); /* eip+sel; rip */ + cpu_stq_data_ra(env, ptr + 0x10, 0, retaddr); /* dp+sel; rdp */ addr = ptr + 0x20; for (i = 0; i < 8; i++) { - tmp = ST(i); + floatx80 tmp = ST(i); helper_fstt(env, tmp, addr, retaddr); addr += 16; } - - if (env->cr[4] & CR4_OSFXSR_MASK) { - /* XXX: finish it */ - cpu_stl_data_ra(env, ptr + 0x18, env->mxcsr, retaddr); /* mxcsr */ - cpu_stl_data_ra(env, ptr + 0x1c, 0x0000ffff, retaddr); /* mxcsr_mask */ - if (env->hflags & HF_CS64_MASK) { - nb_xmm_regs = 16; - } else { - nb_xmm_regs = 8; - } - addr = ptr + 0xa0; - /* Fast FXSAVE leaves out the XMM registers */ - if (!(env->efer & MSR_EFER_FFXSR) - || (env->hflags & HF_CPL_MASK) - || !(env->hflags & HF_LMA_MASK)) { - for (i = 0; i < nb_xmm_regs; i++) { - cpu_stq_data_ra(env, addr, env->xmm_regs[i].ZMM_Q(0), retaddr); - cpu_stq_data_ra(env, addr + 8, env->xmm_regs[i].ZMM_Q(1), retaddr); - addr += 16; - } - } - } } -void helper_fxsave(CPUX86State *env, target_ulong ptr, int data64) +static void do_xsave_mxcsr(CPUX86State *env, target_ulong ptr, uintptr_t retaddr) { - do_fxsave(env, ptr, data64, GETPC()); + cpu_stl_data_ra(env, ptr + 0x18, env->mxcsr, retaddr); /* mxcsr */ + cpu_stl_data_ra(env, ptr + 0x1c, 0x0000ffff, retaddr); /* mxcsr_mask */ } -static void do_fxrstor(CPUX86State *env, target_ulong ptr, int data64, - uintptr_t retaddr) +static void do_xsave_sse(CPUX86State *env, target_ulong ptr, uintptr_t retaddr) { - int i, fpus, fptag, nb_xmm_regs; - floatx80 tmp; + int i, nb_xmm_regs; target_ulong addr; + if (env->hflags & HF_CS64_MASK) { + nb_xmm_regs = 16; + } else { + nb_xmm_regs = 8; + } + + addr = ptr + 0xa0; + for (i = 0; i < nb_xmm_regs; i++) { + cpu_stq_data_ra(env, addr, env->xmm_regs[i].ZMM_Q(0), retaddr); + cpu_stq_data_ra(env, addr + 8, env->xmm_regs[i].ZMM_Q(1), retaddr); + addr += 16; + } +} + +void helper_fxsave(CPUX86State *env, target_ulong ptr) +{ /* The operand must be 16 byte aligned */ if (ptr & 0xf) { - raise_exception_ra(env, EXCP0D_GPF, retaddr); + raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC()); } + do_xsave_fpu(env, ptr, GETPC()); + + if (env->cr[4] & CR4_OSFXSR_MASK) { + do_xsave_mxcsr(env, ptr, GETPC()); + /* Fast FXSAVE leaves out the XMM registers */ + if (!(env->efer & MSR_EFER_FFXSR) + || (env->hflags & HF_CPL_MASK) + || !(env->hflags & HF_LMA_MASK)) { + do_xsave_sse(env, ptr, GETPC()); + } + } +} + +static void do_xrstor_fpu(CPUX86State *env, target_ulong ptr, uintptr_t retaddr) +{ + int i, fpus, fptag; + target_ulong addr; + cpu_set_fpuc(env, cpu_lduw_data_ra(env, ptr, retaddr)); fpus = cpu_lduw_data_ra(env, ptr + 2, retaddr); fptag = cpu_lduw_data_ra(env, ptr + 4, retaddr); @@ -1207,39 +1206,56 @@ static void do_fxrstor(CPUX86State *env, target_ulong ptr, int data64, addr = ptr + 0x20; for (i = 0; i < 8; i++) { - tmp = helper_fldt(env, addr, retaddr); + floatx80 tmp = helper_fldt(env, addr, retaddr); ST(i) = tmp; addr += 16; } +} + +static void do_xrstor_mxcsr(CPUX86State *env, target_ulong ptr, uintptr_t retaddr) +{ + cpu_set_mxcsr(env, cpu_ldl_data_ra(env, ptr + 0x18, retaddr)); +} + +static void do_xrstor_sse(CPUX86State *env, target_ulong ptr, uintptr_t retaddr) +{ + int i, nb_xmm_regs; + target_ulong addr; + + if (env->hflags & HF_CS64_MASK) { + nb_xmm_regs = 16; + } else { + nb_xmm_regs = 8; + } + + addr = ptr + 0xa0; + for (i = 0; i < nb_xmm_regs; i++) { + env->xmm_regs[i].ZMM_Q(0) = cpu_ldq_data_ra(env, addr, retaddr); + env->xmm_regs[i].ZMM_Q(1) = cpu_ldq_data_ra(env, addr + 8, retaddr); + addr += 16; + } +} + +void helper_fxrstor(CPUX86State *env, target_ulong ptr) +{ + /* The operand must be 16 byte aligned */ + if (ptr & 0xf) { + raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC()); + } + + do_xrstor_fpu(env, ptr, GETPC()); if (env->cr[4] & CR4_OSFXSR_MASK) { - /* XXX: finish it */ - cpu_set_mxcsr(env, cpu_ldl_data_ra(env, ptr + 0x18, retaddr)); - /* cpu_ldl_data_ra(env, ptr + 0x1c, retaddr); */ - if (env->hflags & HF_CS64_MASK) { - nb_xmm_regs = 16; - } else { - nb_xmm_regs = 8; - } - addr = ptr + 0xa0; - /* Fast FXRESTORE leaves out the XMM registers */ + do_xrstor_mxcsr(env, ptr, GETPC()); + /* Fast FXRSTOR leaves out the XMM registers */ if (!(env->efer & MSR_EFER_FFXSR) || (env->hflags & HF_CPL_MASK) || !(env->hflags & HF_LMA_MASK)) { - for (i = 0; i < nb_xmm_regs; i++) { - env->xmm_regs[i].ZMM_Q(0) = cpu_ldq_data_ra(env, addr, retaddr); - env->xmm_regs[i].ZMM_Q(1) = cpu_ldq_data_ra(env, addr + 8, retaddr); - addr += 16; - } + do_xrstor_sse(env, ptr, GETPC()); } } } -void helper_fxrstor(CPUX86State *env, target_ulong ptr, int data64) -{ - do_fxrstor(env, ptr, data64, GETPC()); -} - void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f) { CPU_LDoubleU temp; diff --git a/target-i386/helper.h b/target-i386/helper.h index 3a25c3b..6109e46 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -185,8 +185,8 @@ DEF_HELPER_3(fstenv, void, env, tl, int) DEF_HELPER_3(fldenv, void, env, tl, int) DEF_HELPER_3(fsave, void, env, tl, int) DEF_HELPER_3(frstor, void, env, tl, int) -DEF_HELPER_3(fxsave, void, env, tl, int) -DEF_HELPER_3(fxrstor, void, env, tl, int) +DEF_HELPER_FLAGS_2(fxsave, TCG_CALL_NO_WG, void, env, tl) +DEF_HELPER_FLAGS_2(fxrstor, TCG_CALL_NO_WG, void, env, tl) DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(ctz, TCG_CALL_NO_RWG_SE, tl, tl) diff --git a/target-i386/translate.c b/target-i386/translate.c index c8e2799..fec2601 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -7515,7 +7515,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, break; } gen_lea_modrm(env, s, modrm); - gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64)); + gen_helper_fxsave(cpu_env, cpu_A0); break; case 1: /* fxrstor */ if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) || @@ -7526,7 +7526,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, break; } gen_lea_modrm(env, s, modrm); - gen_helper_fxrstor(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64)); + gen_helper_fxrstor(cpu_env, cpu_A0); break; case 2: /* ldmxcsr */ case 3: /* stmxcsr */