diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-06-18 09:32:32 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-06-18 09:32:32 +0000 |
commit | 94451178b6b7d6d08c0f16a5a1b0d03bf978f74b (patch) | |
tree | b794553b91c5562d300e54a1a03c3da6de4b7263 /target-i386 | |
parent | 17ca26e7918353ae67fa9cfcbf61e3b90a1b3a6b (diff) |
HLT, MWAIT and MONITOR insn fixes (initial patch by Alexander Graf)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4746 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/helper.h | 4 | ||||
-rw-r--r-- | target-i386/op_helper.c | 18 | ||||
-rw-r--r-- | target-i386/translate.c | 10 |
3 files changed, 21 insertions, 11 deletions
diff --git a/target-i386/helper.h b/target-i386/helper.h index 1520299148..8df6acc8d6 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -60,9 +60,9 @@ DEF_HELPER(void, helper_sysexit, (void)) DEF_HELPER(void, helper_syscall, (int next_eip_addend)) DEF_HELPER(void, helper_sysret, (int dflag)) #endif -DEF_HELPER(void, helper_hlt, (void)) +DEF_HELPER(void, helper_hlt, (int next_eip_addend)) DEF_HELPER(void, helper_monitor, (target_ulong ptr)) -DEF_HELPER(void, helper_mwait, (void)) +DEF_HELPER(void, helper_mwait, (int next_eip_addend)) DEF_HELPER(void, helper_debug, (void)) DEF_HELPER(void, helper_raise_interrupt, (int intno, int next_eip_addend)) DEF_HELPER(void, helper_raise_exception, (int exception_index)) diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c index 730ec81698..beb568741d 100644 --- a/target-i386/op_helper.c +++ b/target-i386/op_helper.c @@ -4547,16 +4547,22 @@ void helper_idivq_EAX(target_ulong t0) } #endif -void helper_hlt(void) +static void do_hlt(void) { - helper_svm_check_intercept_param(SVM_EXIT_HLT, 0); - env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */ env->halted = 1; env->exception_index = EXCP_HLT; cpu_loop_exit(); } +void helper_hlt(int next_eip_addend) +{ + helper_svm_check_intercept_param(SVM_EXIT_HLT, 0); + EIP += next_eip_addend; + + do_hlt(); +} + void helper_monitor(target_ulong ptr) { if ((uint32_t)ECX != 0) @@ -4565,17 +4571,19 @@ void helper_monitor(target_ulong ptr) helper_svm_check_intercept_param(SVM_EXIT_MONITOR, 0); } -void helper_mwait(void) +void helper_mwait(int next_eip_addend) { if ((uint32_t)ECX != 0) raise_exception(EXCP0D_GPF); helper_svm_check_intercept_param(SVM_EXIT_MWAIT, 0); + EIP += next_eip_addend; + /* XXX: not complete but not completely erroneous */ if (env->cpu_index != 0 || env->next_cpu != NULL) { /* more than one CPU: do not sleep because another CPU may wake this one */ } else { - helper_hlt(); + do_hlt(); } } diff --git a/target-i386/translate.c b/target-i386/translate.c index 14903b4dfe..6f9c25672f 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -6420,8 +6420,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } else { if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); - gen_jmp_im(s->pc - s->cs_base); - tcg_gen_helper_0_0(helper_hlt); + gen_jmp_im(pc_start - s->cs_base); + tcg_gen_helper_0_1(helper_hlt, tcg_const_i32(s->pc - pc_start)); s->is_jmp = 3; } break; @@ -6519,6 +6519,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) goto illegal_op; + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); gen_jmp_im(pc_start - s->cs_base); #ifdef TARGET_X86_64 if (s->aflag == 2) { @@ -6541,8 +6543,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_set_cc_op(s->cc_op); s->cc_op = CC_OP_DYNAMIC; } - gen_jmp_im(s->pc - s->cs_base); - tcg_gen_helper_0_0(helper_mwait); + gen_jmp_im(pc_start - s->cs_base); + tcg_gen_helper_0_1(helper_mwait, tcg_const_i32(s->pc - pc_start)); gen_eob(s); break; default: |