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,6 +1747,9 @@ static void gen_eob(DisasContext *s) | ||
1747 | { | 1747 | { |
1748 | if (s->cc_op != CC_OP_DYNAMIC) | 1748 | if (s->cc_op != CC_OP_DYNAMIC) |
1749 | gen_op_set_cc_op(s->cc_op); | 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 | if (s->singlestep_enabled) { | 1753 | if (s->singlestep_enabled) { |
1751 | gen_op_debug(); | 1754 | gen_op_debug(); |
1752 | } else if (s->tf) { | 1755 | } else if (s->tf) { |
@@ -2385,8 +2388,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2385,8 +2388,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2385 | gen_movl_seg_T0(s, reg, pc_start - s->cs_base); | 2388 | gen_movl_seg_T0(s, reg, pc_start - s->cs_base); |
2386 | gen_pop_update(s); | 2389 | gen_pop_update(s); |
2387 | if (reg == R_SS) { | 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 | s->tf = 0; | 2396 | s->tf = 0; |
2391 | } | 2397 | } |
2392 | if (s->is_jmp) { | 2398 | if (s->is_jmp) { |
@@ -2457,7 +2463,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2457,7 +2463,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2457 | gen_movl_seg_T0(s, reg, pc_start - s->cs_base); | 2463 | gen_movl_seg_T0(s, reg, pc_start - s->cs_base); |
2458 | if (reg == R_SS) { | 2464 | if (reg == R_SS) { |
2459 | /* if reg == SS, inhibit interrupts/trace */ | 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 | s->tf = 0; | 2470 | s->tf = 0; |
2462 | } | 2471 | } |
2463 | if (s->is_jmp) { | 2472 | if (s->is_jmp) { |
@@ -3176,6 +3185,21 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3176,6 +3185,21 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3176 | gen_op_fpop(); | 3185 | gen_op_fpop(); |
3177 | s->cc_op = CC_OP_EFLAGS; | 3186 | s->cc_op = CC_OP_EFLAGS; |
3178 | break; | 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 | default: | 3203 | default: |
3180 | goto illegal_op; | 3204 | goto illegal_op; |
3181 | } | 3205 | } |
@@ -3730,7 +3754,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3730,7 +3754,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3730 | gen_sti: | 3754 | gen_sti: |
3731 | gen_op_sti(); | 3755 | gen_op_sti(); |
3732 | /* interruptions are enabled only the first insn after sti */ | 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 | /* give a chance to handle pending irqs */ | 3761 | /* give a chance to handle pending irqs */ |
3735 | gen_op_jmp_im(s->pc - s->cs_base); | 3762 | gen_op_jmp_im(s->pc - s->cs_base); |
3736 | gen_eob(s); | 3763 | gen_eob(s); |
@@ -4459,7 +4486,8 @@ static inline int gen_intermediate_code_internal(CPUState *env, | @@ -4459,7 +4486,8 @@ static inline int gen_intermediate_code_internal(CPUState *env, | ||
4459 | else | 4486 | else |
4460 | dc->mem_index = 3; | 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 | #ifndef CONFIG_SOFTMMU | 4491 | #ifndef CONFIG_SOFTMMU |
4464 | || (flags & HF_SOFTMMU_MASK) | 4492 | || (flags & HF_SOFTMMU_MASK) |
4465 | #endif | 4493 | #endif |
@@ -4472,12 +4500,6 @@ static inline int gen_intermediate_code_internal(CPUState *env, | @@ -4472,12 +4500,6 @@ static inline int gen_intermediate_code_internal(CPUState *env, | ||
4472 | pc_ptr = pc_start; | 4500 | pc_ptr = pc_start; |
4473 | lj = -1; | 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 | for(;;) { | 4503 | for(;;) { |
4482 | if (env->nb_breakpoints > 0) { | 4504 | if (env->nb_breakpoints > 0) { |
4483 | for(j = 0; j < env->nb_breakpoints; j++) { | 4505 | for(j = 0; j < env->nb_breakpoints; j++) { |
@@ -4504,7 +4526,11 @@ static inline int gen_intermediate_code_internal(CPUState *env, | @@ -4504,7 +4526,11 @@ static inline int gen_intermediate_code_internal(CPUState *env, | ||
4504 | break; | 4526 | break; |
4505 | /* if single step mode, we generate only one instruction and | 4527 | /* if single step mode, we generate only one instruction and |
4506 | generate an exception */ | 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 | gen_op_jmp_im(pc_ptr - dc->cs_base); | 4534 | gen_op_jmp_im(pc_ptr - dc->cs_base); |
4509 | gen_eob(dc); | 4535 | gen_eob(dc); |
4510 | break; | 4536 | break; |