mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-09 10:34:58 -06:00
added fcmovxx support (fixes segfaults in some recent linux tools) - fixed irq inhibit 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
This commit is contained in:
parent
afa05eb15e
commit
a2cc3b2433
1 changed files with 38 additions and 12 deletions
|
@ -1747,6 +1747,9 @@ static void gen_eob(DisasContext *s)
|
||||||
{
|
{
|
||||||
if (s->cc_op != CC_OP_DYNAMIC)
|
if (s->cc_op != CC_OP_DYNAMIC)
|
||||||
gen_op_set_cc_op(s->cc_op);
|
gen_op_set_cc_op(s->cc_op);
|
||||||
|
if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
|
||||||
|
gen_op_reset_inhibit_irq();
|
||||||
|
}
|
||||||
if (s->singlestep_enabled) {
|
if (s->singlestep_enabled) {
|
||||||
gen_op_debug();
|
gen_op_debug();
|
||||||
} else if (s->tf) {
|
} else if (s->tf) {
|
||||||
|
@ -2385,8 +2388,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
||||||
gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
|
gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
|
||||||
gen_pop_update(s);
|
gen_pop_update(s);
|
||||||
if (reg == R_SS) {
|
if (reg == R_SS) {
|
||||||
/* if reg == SS, inhibit interrupts/trace */
|
/* if reg == SS, inhibit interrupts/trace. */
|
||||||
gen_op_set_inhibit_irq();
|
/* If several instructions disable interrupts, only the
|
||||||
|
_first_ does it */
|
||||||
|
if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
|
||||||
|
gen_op_set_inhibit_irq();
|
||||||
s->tf = 0;
|
s->tf = 0;
|
||||||
}
|
}
|
||||||
if (s->is_jmp) {
|
if (s->is_jmp) {
|
||||||
|
@ -2457,7 +2463,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
||||||
gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
|
gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
|
||||||
if (reg == R_SS) {
|
if (reg == R_SS) {
|
||||||
/* if reg == SS, inhibit interrupts/trace */
|
/* if reg == SS, inhibit interrupts/trace */
|
||||||
gen_op_set_inhibit_irq();
|
/* If several instructions disable interrupts, only the
|
||||||
|
_first_ does it */
|
||||||
|
if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
|
||||||
|
gen_op_set_inhibit_irq();
|
||||||
s->tf = 0;
|
s->tf = 0;
|
||||||
}
|
}
|
||||||
if (s->is_jmp) {
|
if (s->is_jmp) {
|
||||||
|
@ -3176,6 +3185,21 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
||||||
gen_op_fpop();
|
gen_op_fpop();
|
||||||
s->cc_op = CC_OP_EFLAGS;
|
s->cc_op = CC_OP_EFLAGS;
|
||||||
break;
|
break;
|
||||||
|
case 0x10 ... 0x13: /* fcmovxx */
|
||||||
|
case 0x18 ... 0x1b:
|
||||||
|
{
|
||||||
|
int op1;
|
||||||
|
const static uint8_t fcmov_cc[8] = {
|
||||||
|
(JCC_B << 1),
|
||||||
|
(JCC_Z << 1),
|
||||||
|
(JCC_BE << 1),
|
||||||
|
(JCC_P << 1),
|
||||||
|
};
|
||||||
|
op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
|
||||||
|
gen_setcc(s, op1);
|
||||||
|
gen_op_fcmov_ST0_STN_T0(opreg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
}
|
}
|
||||||
|
@ -3730,7 +3754,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
||||||
gen_sti:
|
gen_sti:
|
||||||
gen_op_sti();
|
gen_op_sti();
|
||||||
/* interruptions are enabled only the first insn after sti */
|
/* interruptions are enabled only the first insn after sti */
|
||||||
gen_op_set_inhibit_irq();
|
/* If several instructions disable interrupts, only the
|
||||||
|
_first_ does it */
|
||||||
|
if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
|
||||||
|
gen_op_set_inhibit_irq();
|
||||||
/* give a chance to handle pending irqs */
|
/* give a chance to handle pending irqs */
|
||||||
gen_op_jmp_im(s->pc - s->cs_base);
|
gen_op_jmp_im(s->pc - s->cs_base);
|
||||||
gen_eob(s);
|
gen_eob(s);
|
||||||
|
@ -4459,7 +4486,8 @@ static inline int gen_intermediate_code_internal(CPUState *env,
|
||||||
else
|
else
|
||||||
dc->mem_index = 3;
|
dc->mem_index = 3;
|
||||||
}
|
}
|
||||||
dc->jmp_opt = !(dc->tf || env->singlestep_enabled
|
dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
|
||||||
|
(flags & HF_INHIBIT_IRQ_MASK)
|
||||||
#ifndef CONFIG_SOFTMMU
|
#ifndef CONFIG_SOFTMMU
|
||||||
|| (flags & HF_SOFTMMU_MASK)
|
|| (flags & HF_SOFTMMU_MASK)
|
||||||
#endif
|
#endif
|
||||||
|
@ -4472,12 +4500,6 @@ static inline int gen_intermediate_code_internal(CPUState *env,
|
||||||
pc_ptr = pc_start;
|
pc_ptr = pc_start;
|
||||||
lj = -1;
|
lj = -1;
|
||||||
|
|
||||||
/* if irq were inhibited for the next instruction, we can disable
|
|
||||||
them here as it is simpler (otherwise jumps would have to
|
|
||||||
handled as special case) */
|
|
||||||
if (flags & HF_INHIBIT_IRQ_MASK) {
|
|
||||||
gen_op_reset_inhibit_irq();
|
|
||||||
}
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (env->nb_breakpoints > 0) {
|
if (env->nb_breakpoints > 0) {
|
||||||
for(j = 0; j < env->nb_breakpoints; j++) {
|
for(j = 0; j < env->nb_breakpoints; j++) {
|
||||||
|
@ -4504,7 +4526,11 @@ static inline int gen_intermediate_code_internal(CPUState *env,
|
||||||
break;
|
break;
|
||||||
/* if single step mode, we generate only one instruction and
|
/* if single step mode, we generate only one instruction and
|
||||||
generate an exception */
|
generate an exception */
|
||||||
if (dc->tf || dc->singlestep_enabled) {
|
/* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
|
||||||
|
the flag and abort the translation to give the irqs a
|
||||||
|
change to be happen */
|
||||||
|
if (dc->tf || dc->singlestep_enabled ||
|
||||||
|
(flags & HF_INHIBIT_IRQ_MASK)) {
|
||||||
gen_op_jmp_im(pc_ptr - dc->cs_base);
|
gen_op_jmp_im(pc_ptr - dc->cs_base);
|
||||||
gen_eob(dc);
|
gen_eob(dc);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue