Commit a2cc3b24334643ddba2f9aa740392162285aa58b

Authored by bellard
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;