Commit a2cc3b24334643ddba2f9aa740392162285aa58b
1 parent
afa05eb1
added fcmovxx support (fixes segfaults in some recent linux tools) - fixed irq i…
…nhibit logic : the irqs are inhibited only for one instruction after, even if the next one also inhibit irqs - stop translation after irq inhibition stops to give a chance to irqs (fixes install NT kernel startup) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@467 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
38 additions
and
12 deletions
target-i386/translate.c
... | ... | @@ -1747,6 +1747,9 @@ static void gen_eob(DisasContext *s) |
1747 | 1747 | { |
1748 | 1748 | if (s->cc_op != CC_OP_DYNAMIC) |
1749 | 1749 | gen_op_set_cc_op(s->cc_op); |
1750 | + if (s->tb->flags & HF_INHIBIT_IRQ_MASK) { | |
1751 | + gen_op_reset_inhibit_irq(); | |
1752 | + } | |
1750 | 1753 | if (s->singlestep_enabled) { |
1751 | 1754 | gen_op_debug(); |
1752 | 1755 | } else if (s->tf) { |
... | ... | @@ -2385,8 +2388,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2385 | 2388 | gen_movl_seg_T0(s, reg, pc_start - s->cs_base); |
2386 | 2389 | gen_pop_update(s); |
2387 | 2390 | if (reg == R_SS) { |
2388 | - /* if reg == SS, inhibit interrupts/trace */ | |
2389 | - gen_op_set_inhibit_irq(); | |
2391 | + /* if reg == SS, inhibit interrupts/trace. */ | |
2392 | + /* If several instructions disable interrupts, only the | |
2393 | + _first_ does it */ | |
2394 | + if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) | |
2395 | + gen_op_set_inhibit_irq(); | |
2390 | 2396 | s->tf = 0; |
2391 | 2397 | } |
2392 | 2398 | if (s->is_jmp) { |
... | ... | @@ -2457,7 +2463,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
2457 | 2463 | gen_movl_seg_T0(s, reg, pc_start - s->cs_base); |
2458 | 2464 | if (reg == R_SS) { |
2459 | 2465 | /* if reg == SS, inhibit interrupts/trace */ |
2460 | - gen_op_set_inhibit_irq(); | |
2466 | + /* If several instructions disable interrupts, only the | |
2467 | + _first_ does it */ | |
2468 | + if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) | |
2469 | + gen_op_set_inhibit_irq(); | |
2461 | 2470 | s->tf = 0; |
2462 | 2471 | } |
2463 | 2472 | if (s->is_jmp) { |
... | ... | @@ -3176,6 +3185,21 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3176 | 3185 | gen_op_fpop(); |
3177 | 3186 | s->cc_op = CC_OP_EFLAGS; |
3178 | 3187 | break; |
3188 | + case 0x10 ... 0x13: /* fcmovxx */ | |
3189 | + case 0x18 ... 0x1b: | |
3190 | + { | |
3191 | + int op1; | |
3192 | + const static uint8_t fcmov_cc[8] = { | |
3193 | + (JCC_B << 1), | |
3194 | + (JCC_Z << 1), | |
3195 | + (JCC_BE << 1), | |
3196 | + (JCC_P << 1), | |
3197 | + }; | |
3198 | + op1 = fcmov_cc[op & 3] | ((op >> 3) & 1); | |
3199 | + gen_setcc(s, op1); | |
3200 | + gen_op_fcmov_ST0_STN_T0(opreg); | |
3201 | + } | |
3202 | + break; | |
3179 | 3203 | default: |
3180 | 3204 | goto illegal_op; |
3181 | 3205 | } |
... | ... | @@ -3730,7 +3754,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
3730 | 3754 | gen_sti: |
3731 | 3755 | gen_op_sti(); |
3732 | 3756 | /* interruptions are enabled only the first insn after sti */ |
3733 | - gen_op_set_inhibit_irq(); | |
3757 | + /* If several instructions disable interrupts, only the | |
3758 | + _first_ does it */ | |
3759 | + if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) | |
3760 | + gen_op_set_inhibit_irq(); | |
3734 | 3761 | /* give a chance to handle pending irqs */ |
3735 | 3762 | gen_op_jmp_im(s->pc - s->cs_base); |
3736 | 3763 | gen_eob(s); |
... | ... | @@ -4459,7 +4486,8 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
4459 | 4486 | else |
4460 | 4487 | dc->mem_index = 3; |
4461 | 4488 | } |
4462 | - dc->jmp_opt = !(dc->tf || env->singlestep_enabled | |
4489 | + dc->jmp_opt = !(dc->tf || env->singlestep_enabled || | |
4490 | + (flags & HF_INHIBIT_IRQ_MASK) | |
4463 | 4491 | #ifndef CONFIG_SOFTMMU |
4464 | 4492 | || (flags & HF_SOFTMMU_MASK) |
4465 | 4493 | #endif |
... | ... | @@ -4472,12 +4500,6 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
4472 | 4500 | pc_ptr = pc_start; |
4473 | 4501 | lj = -1; |
4474 | 4502 | |
4475 | - /* if irq were inhibited for the next instruction, we can disable | |
4476 | - them here as it is simpler (otherwise jumps would have to | |
4477 | - handled as special case) */ | |
4478 | - if (flags & HF_INHIBIT_IRQ_MASK) { | |
4479 | - gen_op_reset_inhibit_irq(); | |
4480 | - } | |
4481 | 4503 | for(;;) { |
4482 | 4504 | if (env->nb_breakpoints > 0) { |
4483 | 4505 | for(j = 0; j < env->nb_breakpoints; j++) { |
... | ... | @@ -4504,7 +4526,11 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
4504 | 4526 | break; |
4505 | 4527 | /* if single step mode, we generate only one instruction and |
4506 | 4528 | generate an exception */ |
4507 | - if (dc->tf || dc->singlestep_enabled) { | |
4529 | + /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear | |
4530 | + the flag and abort the translation to give the irqs a | |
4531 | + change to be happen */ | |
4532 | + if (dc->tf || dc->singlestep_enabled || | |
4533 | + (flags & HF_INHIBIT_IRQ_MASK)) { | |
4508 | 4534 | gen_op_jmp_im(pc_ptr - dc->cs_base); |
4509 | 4535 | gen_eob(dc); |
4510 | 4536 | break; | ... | ... |