Merge remote-tracking branch 'remotes/rth/tags/x86-next-20141214' into staging Collected x86 patches # gpg: Signature made Sun 14 Dec 2014 22:54:28 GMT using RSA key ID 4DD0279B # gpg: Good signature from "Richard Henderson <rth7680@gmail.com>" # gpg: aka "Richard Henderson <rth@redhat.com>" # gpg: aka "Richard Henderson <rth@twiddle.net>" * remotes/rth/tags/x86-next-20141214: target-i386: fix icount processing for repz instructions target-i386: fbld instruction doesn't set minus sign target-i386: Wrong conversion infinity from float80 to int32/int64 Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c index 1d4eee3..30d34d5 100644 --- a/target-i386/fpu_helper.c +++ b/target-i386/fpu_helper.c
@@ -251,16 +251,34 @@ int32_t helper_fistl_ST0(CPUX86State *env) { int32_t val; + signed char old_exp_flags; + + old_exp_flags = get_float_exception_flags(&env->fp_status); + set_float_exception_flags(0, &env->fp_status); val = floatx80_to_int32(ST0, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) { + val = 0x80000000; + } + set_float_exception_flags(get_float_exception_flags(&env->fp_status) + | old_exp_flags, &env->fp_status); return val; } int64_t helper_fistll_ST0(CPUX86State *env) { int64_t val; + signed char old_exp_flags; - val = floatx80_to_int64(ST0, &env->fp_status); + old_exp_flags = get_float_exception_flags(&env->fp_status); + set_float_exception_flags(0, &env->fp_status); + + val = floatx80_to_int32(ST0, &env->fp_status); + if (get_float_exception_flags(&env->fp_status) & float_flag_invalid) { + val = 0x8000000000000000ULL; + } + set_float_exception_flags(get_float_exception_flags(&env->fp_status) + | old_exp_flags, &env->fp_status); return val; } @@ -621,7 +639,7 @@ } tmp = int64_to_floatx80(val, &env->fp_status); if (cpu_ldub_data(env, ptr + 9) & 0x80) { - floatx80_chs(tmp); + tmp = floatx80_chs(tmp); } fpush(env); ST0 = tmp;
diff --git a/target-i386/translate.c b/target-i386/translate.c index 782f7d2..6243e36 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c
@@ -115,6 +115,7 @@ int tf; /* TF cpu flag */ int singlestep_enabled; /* "hardware" single step enabled */ int jmp_opt; /* use direct block chaining for direct jumps */ + int repz_opt; /* optimize jumps within repz instructions */ int mem_index; /* select memory access functions */ uint64_t flags; /* all execution flags */ struct TranslationBlock *tb; @@ -1215,7 +1216,7 @@ gen_op_add_reg_im(s->aflag, R_ECX, -1); \ /* a loop would cause two single step exceptions if ECX = 1 \ before rep string_insn */ \ - if (!s->jmp_opt) \ + if (s->repz_opt) \ gen_op_jz_ecx(s->aflag, l2); \ gen_jmp(s, cur_eip); \ } @@ -1233,7 +1234,7 @@ gen_op_add_reg_im(s->aflag, R_ECX, -1); \ gen_update_cc_op(s); \ gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \ - if (!s->jmp_opt) \ + if (s->repz_opt) \ gen_op_jz_ecx(s->aflag, l2); \ gen_jmp(s, cur_eip); \ } @@ -7951,6 +7952,17 @@ || (flags & HF_SOFTMMU_MASK) #endif ); + /* Do not optimize repz jumps at all in icount mode, because + rep movsS instructions are execured with different paths + in !repz_opt and repz_opt modes. The first one was used + always except single step mode. And this setting + disables jumps optimization and control paths become + equivalent in run and single step modes. + Now there will be no jump optimization for repz in + record/replay modes and there will always be an + additional step for ecx=0 when icount is enabled. + */ + dc->repz_opt = !dc->jmp_opt && !use_icount; #if 0 /* check addseg logic */ if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))