diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-12-15 11:11:52 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-12-15 11:11:52 +0000 |
commit | 54600752a1dd67844c2cf3c467db562c39499838 (patch) | |
tree | 2f065eb41cb578b6317bcd8172bc832e806d731e | |
parent | e0d3795654b7eb5b91b478bc7e6b717b192a8bce (diff) | |
parent | c4d4525c38cd93cc5d1a743976eb25ac571d435f (diff) |
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>
-rw-r--r-- | target-i386/fpu_helper.c | 22 | ||||
-rw-r--r-- | target-i386/translate.c | 16 |
2 files changed, 34 insertions, 4 deletions
diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c index 1d4eee3974..30d34d5aee 100644 --- a/target-i386/fpu_helper.c +++ b/target-i386/fpu_helper.c @@ -251,16 +251,34 @@ int32_t helper_fist_ST0(CPUX86State *env) 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 @@ void helper_fbld_ST0(CPUX86State *env, target_ulong ptr) } 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 782f7d2666..6243e36661 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -115,6 +115,7 @@ typedef struct DisasContext { 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 @@ static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \ 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 @@ static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \ 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 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, || (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)) |