We will be able to reuse these pieces for XSAVE/XRSTOR. Signed-off-by: Richard Henderson <r...@twiddle.net> --- target-i386/fpu_helper.c | 145 ++++++++++++++++++++++++++++------------------- target-i386/helper.h | 4 +- target-i386/translate.c | 4 +- 3 files changed, 90 insertions(+), 63 deletions(-)
diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c index 30d34d5..1d72cd1 100644 --- a/target-i386/fpu_helper.c +++ b/target-i386/fpu_helper.c @@ -1101,17 +1101,11 @@ void cpu_x86_frstor(CPUX86State *env, target_ulong ptr, int data32) } #endif -void helper_fxsave(CPUX86State *env, target_ulong ptr, int data64) +static void do_xsave_fpu(CPUX86State *env, target_ulong ptr) { - 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(env, EXCP0D_GPF); - } - fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; fptag = 0; for (i = 0; i < 8; i++) { @@ -1120,60 +1114,71 @@ void helper_fxsave(CPUX86State *env, target_ulong ptr, int data64) cpu_stw_data(env, ptr, env->fpuc); cpu_stw_data(env, ptr + 2, fpus); cpu_stw_data(env, ptr + 4, fptag ^ 0xff); -#ifdef TARGET_X86_64 - if (data64) { - cpu_stq_data(env, ptr + 0x08, 0); /* rip */ - cpu_stq_data(env, ptr + 0x10, 0); /* rdp */ - } else -#endif - { - cpu_stl_data(env, ptr + 0x08, 0); /* eip */ - cpu_stl_data(env, ptr + 0x0c, 0); /* sel */ - cpu_stl_data(env, ptr + 0x10, 0); /* dp */ - cpu_stl_data(env, ptr + 0x14, 0); /* 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(env, ptr + 0x08, 0); /* eip+sel; rip */ + cpu_stq_data(env, ptr + 0x10, 0); /* edp+sel; rdp */ addr = ptr + 0x20; for (i = 0; i < 8; i++) { - tmp = ST(i); + floatx80 tmp = ST(i); helper_fstt(env, tmp, addr); addr += 16; } +} + +static void do_xsave_mxcsr(CPUX86State *env, target_ulong ptr) +{ + cpu_stl_data(env, ptr + 0x18, env->mxcsr); /* mxcsr */ + cpu_stl_data(env, ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */ +} + +static void do_xsave_sse(CPUX86State *env, target_ulong ptr) +{ + 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(env, addr, env->xmm_regs[i].XMM_Q(0)); + cpu_stq_data(env, addr + 8, env->xmm_regs[i].XMM_Q(1)); + addr += 16; + } +} + +void helper_fxsave(CPUX86State *env, target_ulong ptr) +{ + /* The operand must be 16 byte aligned */ + if (ptr & 0xf) { + raise_exception(env, EXCP0D_GPF); + } + + do_xsave_fpu(env, ptr); if (env->cr[4] & CR4_OSFXSR_MASK) { - /* XXX: finish it */ - cpu_stl_data(env, ptr + 0x18, env->mxcsr); /* mxcsr */ - cpu_stl_data(env, ptr + 0x1c, 0x0000ffff); /* mxcsr_mask */ - if (env->hflags & HF_CS64_MASK) { - nb_xmm_regs = 16; - } else { - nb_xmm_regs = 8; - } - addr = ptr + 0xa0; + do_xsave_mxcsr(env, ptr); /* 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(env, addr, env->xmm_regs[i].XMM_Q(0)); - cpu_stq_data(env, addr + 8, env->xmm_regs[i].XMM_Q(1)); - addr += 16; - } + do_xsave_sse(env, ptr); } } } -void helper_fxrstor(CPUX86State *env, target_ulong ptr, int data64) +static void do_xrstor_fpu(CPUX86State *env, target_ulong ptr) { - int i, fpus, fptag, nb_xmm_regs; - floatx80 tmp; + int i, fpus, fptag; target_ulong addr; - /* The operand must be 16 byte aligned */ - if (ptr & 0xf) { - raise_exception(env, EXCP0D_GPF); - } - cpu_set_fpuc(env, cpu_lduw_data(env, ptr)); fpus = cpu_lduw_data(env, ptr + 2); fptag = cpu_lduw_data(env, ptr + 4); @@ -1186,30 +1191,52 @@ void helper_fxrstor(CPUX86State *env, target_ulong ptr, int data64) addr = ptr + 0x20; for (i = 0; i < 8; i++) { - tmp = helper_fldt(env, addr); + floatx80 tmp = helper_fldt(env, addr); ST(i) = tmp; addr += 16; } +} + +static void do_xrstor_mxcsr(CPUX86State *env, target_ulong ptr) +{ + cpu_set_mxcsr(env, cpu_ldl_data(env, ptr + 0x18)); +} + +static void do_xrstor_sse(CPUX86State *env, target_ulong ptr) +{ + 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].XMM_Q(0) = cpu_ldq_data(env, addr); + env->xmm_regs[i].XMM_Q(1) = cpu_ldq_data(env, addr + 8); + addr += 16; + } +} + +void helper_fxrstor(CPUX86State *env, target_ulong ptr) +{ + /* The operand must be 16 byte aligned */ + if (ptr & 0xf) { + raise_exception(env, EXCP0D_GPF); + } + + do_xrstor_fpu(env, ptr); if (env->cr[4] & CR4_OSFXSR_MASK) { - /* XXX: finish it */ - cpu_set_mxcsr(env, cpu_ldl_data(env, ptr + 0x18)); - /* cpu_ldl_data(env, ptr + 0x1c); */ - 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); + /* 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].XMM_Q(0) = cpu_ldq_data(env, addr); - env->xmm_regs[i].XMM_Q(1) = cpu_ldq_data(env, addr + 8); - addr += 16; - } + do_xrstor_sse(env, ptr); } } } diff --git a/target-i386/helper.h b/target-i386/helper.h index 903197b..7fc8697 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -183,8 +183,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 72f8df9..4216ecb 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -7585,7 +7585,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_lea_modrm(env, s, modrm); gen_update_cc_op(s); gen_jmp_im(pc_start - s->cs_base); - 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) || @@ -7598,7 +7598,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_lea_modrm(env, s, modrm); gen_update_cc_op(s); gen_jmp_im(pc_start - s->cs_base); - 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 */ -- 2.4.3