mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 07:13:54 -06:00
target/i386: do not trigger IRQ shadow for LSS
Because LSS need not trigger an IRQ shadow, gen_movl_seg can't just use the destination register to decide whether to inhibit IRQs. Add an argument. Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
785f945bd5
commit
e54ef98c8a
2 changed files with 18 additions and 13 deletions
|
@ -342,7 +342,7 @@ static void gen_writeback(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv
|
||||||
break;
|
break;
|
||||||
case X86_OP_SEG:
|
case X86_OP_SEG:
|
||||||
/* Note that gen_movl_seg takes care of interrupt shadow and TF. */
|
/* Note that gen_movl_seg takes care of interrupt shadow and TF. */
|
||||||
gen_movl_seg(s, op->n, s->T0);
|
gen_movl_seg(s, op->n, v, op->n == R_SS);
|
||||||
break;
|
break;
|
||||||
case X86_OP_INT:
|
case X86_OP_INT:
|
||||||
if (op->has_ea) {
|
if (op->has_ea) {
|
||||||
|
@ -2382,7 +2382,7 @@ static void gen_lxx_seg(DisasContext *s, X86DecodedInsn *decode, int seg)
|
||||||
gen_op_ld_v(s, MO_16, s->T1, s->A0);
|
gen_op_ld_v(s, MO_16, s->T1, s->A0);
|
||||||
|
|
||||||
/* load the segment here to handle exceptions properly */
|
/* load the segment here to handle exceptions properly */
|
||||||
gen_movl_seg(s, seg, s->T1);
|
gen_movl_seg(s, seg, s->T1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_LDS(DisasContext *s, X86DecodedInsn *decode)
|
static void gen_LDS(DisasContext *s, X86DecodedInsn *decode)
|
||||||
|
|
|
@ -2026,27 +2026,32 @@ static void gen_op_movl_seg_real(DisasContext *s, X86Seg seg_reg, TCGv seg)
|
||||||
|
|
||||||
/* move SRC to seg_reg and compute if the CPU state may change. Never
|
/* move SRC to seg_reg and compute if the CPU state may change. Never
|
||||||
call this function with seg_reg == R_CS */
|
call this function with seg_reg == R_CS */
|
||||||
static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src)
|
static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src, bool inhibit_irq)
|
||||||
{
|
{
|
||||||
if (PE(s) && !VM86(s)) {
|
if (PE(s) && !VM86(s)) {
|
||||||
TCGv_i32 sel = tcg_temp_new_i32();
|
TCGv_i32 sel = tcg_temp_new_i32();
|
||||||
|
|
||||||
tcg_gen_trunc_tl_i32(sel, src);
|
tcg_gen_trunc_tl_i32(sel, src);
|
||||||
gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), sel);
|
gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), sel);
|
||||||
/* abort translation because the addseg value may change or
|
|
||||||
because ss32 may change. For R_SS, translation must always
|
/* For move to DS/ES/SS, the addseg or ss32 flags may change. */
|
||||||
stop as a special handling must be done to disable hardware
|
if (CODE32(s) && seg_reg < R_FS) {
|
||||||
interrupts for the next instruction */
|
|
||||||
if (seg_reg == R_SS) {
|
|
||||||
s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
|
|
||||||
} else if (CODE32(s) && seg_reg < R_FS) {
|
|
||||||
s->base.is_jmp = DISAS_EOB_NEXT;
|
s->base.is_jmp = DISAS_EOB_NEXT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
gen_op_movl_seg_real(s, seg_reg, src);
|
gen_op_movl_seg_real(s, seg_reg, src);
|
||||||
if (seg_reg == R_SS) {
|
}
|
||||||
s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
|
|
||||||
}
|
/*
|
||||||
|
* For MOV or POP to SS (but not LSS) translation must always
|
||||||
|
* stop as a special handling must be done to disable hardware
|
||||||
|
* interrupts for the next instruction.
|
||||||
|
*
|
||||||
|
* DISAS_EOB_INHIBIT_IRQ is a superset of DISAS_EOB_NEXT which
|
||||||
|
* might have been set above.
|
||||||
|
*/
|
||||||
|
if (inhibit_irq) {
|
||||||
|
s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue