mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
fixed eflags IF/IOPL update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@476 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
6dca2016fc
commit
4136f33c7e
4 changed files with 70 additions and 59 deletions
|
@ -512,11 +512,6 @@ static inline uint32_t compute_eflags(void)
|
||||||
return env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
|
return env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK)
|
|
||||||
|
|
||||||
#define FL_UPDATE_CPL0_MASK (TF_MASK | IF_MASK | IOPL_MASK | NT_MASK | \
|
|
||||||
RF_MASK | AC_MASK | ID_MASK)
|
|
||||||
|
|
||||||
/* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */
|
/* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */
|
||||||
static inline void load_eflags(int eflags, int update_mask)
|
static inline void load_eflags(int eflags, int update_mask)
|
||||||
{
|
{
|
||||||
|
|
|
@ -419,7 +419,8 @@ static void switch_tss(int tss_selector,
|
||||||
/* load all registers without an exception, then reload them with
|
/* load all registers without an exception, then reload them with
|
||||||
possible exception */
|
possible exception */
|
||||||
env->eip = new_eip;
|
env->eip = new_eip;
|
||||||
eflags_mask = FL_UPDATE_CPL0_MASK;
|
eflags_mask = TF_MASK | AC_MASK | ID_MASK |
|
||||||
|
IF_MASK | IOPL_MASK | VM_MASK | RF_MASK;
|
||||||
if (!(type & 8))
|
if (!(type & 8))
|
||||||
eflags_mask &= 0xffff;
|
eflags_mask &= 0xffff;
|
||||||
load_eflags(new_eflags, eflags_mask);
|
load_eflags(new_eflags, eflags_mask);
|
||||||
|
@ -575,27 +576,6 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
|
||||||
uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
|
uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
|
||||||
uint32_t old_eip;
|
uint32_t old_eip;
|
||||||
|
|
||||||
#ifdef DEBUG_PCALL
|
|
||||||
if (loglevel) {
|
|
||||||
static int count;
|
|
||||||
fprintf(logfile, "%d: interrupt: vector=%02x error_code=%04x int=%d CS:IP=%04x:%08x CPL=%d\n",
|
|
||||||
count, intno, error_code, is_int, env->segs[R_CS].selector, env->eip, env->hflags & 3);
|
|
||||||
#if 0
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
uint8_t *ptr;
|
|
||||||
printf(" code=");
|
|
||||||
ptr = env->segs[R_CS].base + env->eip;
|
|
||||||
for(i = 0; i < 16; i++) {
|
|
||||||
printf(" %02x", ldub(ptr + i));
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
has_error_code = 0;
|
has_error_code = 0;
|
||||||
if (!is_int && !is_hw) {
|
if (!is_int && !is_hw) {
|
||||||
switch(intno) {
|
switch(intno) {
|
||||||
|
@ -775,7 +755,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
|
||||||
|
|
||||||
/* real mode interrupt */
|
/* real mode interrupt */
|
||||||
static void do_interrupt_real(int intno, int is_int, int error_code,
|
static void do_interrupt_real(int intno, int is_int, int error_code,
|
||||||
unsigned int next_eip)
|
unsigned int next_eip)
|
||||||
{
|
{
|
||||||
SegmentCache *dt;
|
SegmentCache *dt;
|
||||||
uint8_t *ptr, *ssp;
|
uint8_t *ptr, *ssp;
|
||||||
|
@ -844,6 +824,27 @@ void do_interrupt_user(int intno, int is_int, int error_code,
|
||||||
void do_interrupt(int intno, int is_int, int error_code,
|
void do_interrupt(int intno, int is_int, int error_code,
|
||||||
unsigned int next_eip, int is_hw)
|
unsigned int next_eip, int is_hw)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_PCALL
|
||||||
|
if (loglevel) {
|
||||||
|
static int count;
|
||||||
|
fprintf(logfile, "%d: interrupt: vector=%02x error_code=%04x int=%d\n",
|
||||||
|
count, intno, error_code, is_int);
|
||||||
|
cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP);
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint8_t *ptr;
|
||||||
|
printf(" code=");
|
||||||
|
ptr = env->segs[R_CS].base + env->eip;
|
||||||
|
for(i = 0; i < 16; i++) {
|
||||||
|
printf(" %02x", ldub(ptr + i));
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (env->cr[0] & CR0_PE_MASK) {
|
if (env->cr[0] & CR0_PE_MASK) {
|
||||||
do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
|
do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1293,6 +1294,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip)
|
||||||
if (loglevel) {
|
if (loglevel) {
|
||||||
fprintf(logfile, "lcall %04x:%08x\n",
|
fprintf(logfile, "lcall %04x:%08x\n",
|
||||||
new_cs, new_eip);
|
new_cs, new_eip);
|
||||||
|
cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if ((new_cs & 0xfffc) == 0)
|
if ((new_cs & 0xfffc) == 0)
|
||||||
|
@ -1493,13 +1495,13 @@ void helper_iret_real(int shift)
|
||||||
POPW(ssp, sp, sp_mask, new_cs);
|
POPW(ssp, sp, sp_mask, new_cs);
|
||||||
POPW(ssp, sp, sp_mask, new_eflags);
|
POPW(ssp, sp, sp_mask, new_eflags);
|
||||||
}
|
}
|
||||||
ESP = (ESP & ~sp_mask) | (sp & 0xffff);
|
ESP = (ESP & ~sp_mask) | (sp & sp_mask);
|
||||||
load_seg_vm(R_CS, new_cs);
|
load_seg_vm(R_CS, new_cs);
|
||||||
env->eip = new_eip;
|
env->eip = new_eip;
|
||||||
if (env->eflags & VM_MASK)
|
if (env->eflags & VM_MASK)
|
||||||
eflags_mask = FL_UPDATE_MASK32 | IF_MASK | RF_MASK;
|
eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK;
|
||||||
else
|
else
|
||||||
eflags_mask = FL_UPDATE_CPL0_MASK;
|
eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK;
|
||||||
if (shift == 0)
|
if (shift == 0)
|
||||||
eflags_mask &= 0xffff;
|
eflags_mask &= 0xffff;
|
||||||
load_eflags(new_eflags, eflags_mask);
|
load_eflags(new_eflags, eflags_mask);
|
||||||
|
@ -1511,7 +1513,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
|
||||||
uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss, sp_mask;
|
uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss, sp_mask;
|
||||||
uint32_t new_es, new_ds, new_fs, new_gs;
|
uint32_t new_es, new_ds, new_fs, new_gs;
|
||||||
uint32_t e1, e2, ss_e1, ss_e2;
|
uint32_t e1, e2, ss_e1, ss_e2;
|
||||||
int cpl, dpl, rpl, eflags_mask;
|
int cpl, dpl, rpl, eflags_mask, iopl;
|
||||||
uint8_t *ssp;
|
uint8_t *ssp;
|
||||||
|
|
||||||
sp_mask = get_sp_mask(env->segs[R_SS].flags);
|
sp_mask = get_sp_mask(env->segs[R_SS].flags);
|
||||||
|
@ -1536,8 +1538,9 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_PCALL
|
#ifdef DEBUG_PCALL
|
||||||
if (loglevel) {
|
if (loglevel) {
|
||||||
fprintf(logfile, "lret new %04x:%08x\n",
|
fprintf(logfile, "lret new %04x:%08x addend=0x%x\n",
|
||||||
new_cs, new_eip);
|
new_cs, new_eip, addend);
|
||||||
|
cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if ((new_cs & 0xfffc) == 0)
|
if ((new_cs & 0xfffc) == 0)
|
||||||
|
@ -1611,11 +1614,13 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
|
||||||
ESP = (ESP & ~sp_mask) | (sp & sp_mask);
|
ESP = (ESP & ~sp_mask) | (sp & sp_mask);
|
||||||
env->eip = new_eip;
|
env->eip = new_eip;
|
||||||
if (is_iret) {
|
if (is_iret) {
|
||||||
/* NOTE: 'cpl' can be different from the current CPL */
|
/* NOTE: 'cpl' is the _old_ CPL */
|
||||||
|
eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK;
|
||||||
if (cpl == 0)
|
if (cpl == 0)
|
||||||
eflags_mask = FL_UPDATE_CPL0_MASK;
|
eflags_mask |= IOPL_MASK;
|
||||||
else
|
iopl = (env->eflags >> IOPL_SHIFT) & 3;
|
||||||
eflags_mask = FL_UPDATE_MASK32;
|
if (cpl <= iopl)
|
||||||
|
eflags_mask |= IF_MASK;
|
||||||
if (shift == 0)
|
if (shift == 0)
|
||||||
eflags_mask &= 0xffff;
|
eflags_mask &= 0xffff;
|
||||||
load_eflags(new_eflags, eflags_mask);
|
load_eflags(new_eflags, eflags_mask);
|
||||||
|
@ -1631,7 +1636,8 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
|
||||||
POPL(ssp, sp, sp_mask, new_gs);
|
POPL(ssp, sp, sp_mask, new_gs);
|
||||||
|
|
||||||
/* modify processor state */
|
/* modify processor state */
|
||||||
load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK);
|
load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK |
|
||||||
|
IF_MASK | IOPL_MASK | VM_MASK | VIF_MASK | VIP_MASK);
|
||||||
load_seg_vm(R_CS, new_cs & 0xffff);
|
load_seg_vm(R_CS, new_cs & 0xffff);
|
||||||
cpu_x86_set_cpl(env, 3);
|
cpu_x86_set_cpl(env, 3);
|
||||||
load_seg_vm(R_SS, new_ss & 0xffff);
|
load_seg_vm(R_SS, new_ss & 0xffff);
|
||||||
|
|
|
@ -1138,38 +1138,36 @@ void OPPROTO op_set_cc_op(void)
|
||||||
CC_OP = PARAM1;
|
CC_OP = PARAM1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FL_UPDATE_MASK16 (FL_UPDATE_MASK32 & 0xffff)
|
/* XXX: clear VIF/VIP in all ops ? */
|
||||||
|
|
||||||
void OPPROTO op_movl_eflags_T0(void)
|
void OPPROTO op_movl_eflags_T0(void)
|
||||||
{
|
{
|
||||||
int eflags;
|
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK));
|
||||||
eflags = T0;
|
|
||||||
CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
|
|
||||||
DF = 1 - (2 * ((eflags >> 10) & 1));
|
|
||||||
/* we also update some system flags as in user mode */
|
|
||||||
env->eflags = (env->eflags & ~FL_UPDATE_MASK32) |
|
|
||||||
(eflags & FL_UPDATE_MASK32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_movw_eflags_T0(void)
|
void OPPROTO op_movw_eflags_T0(void)
|
||||||
{
|
{
|
||||||
int eflags;
|
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK) & 0xffff);
|
||||||
eflags = T0;
|
}
|
||||||
CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
|
|
||||||
DF = 1 - (2 * ((eflags >> 10) & 1));
|
void OPPROTO op_movl_eflags_T0_io(void)
|
||||||
/* we also update some system flags as in user mode */
|
{
|
||||||
env->eflags = (env->eflags & ~FL_UPDATE_MASK16) |
|
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK));
|
||||||
(eflags & FL_UPDATE_MASK16);
|
}
|
||||||
|
|
||||||
|
void OPPROTO op_movw_eflags_T0_io(void)
|
||||||
|
{
|
||||||
|
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK) & 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_movl_eflags_T0_cpl0(void)
|
void OPPROTO op_movl_eflags_T0_cpl0(void)
|
||||||
{
|
{
|
||||||
load_eflags(T0, FL_UPDATE_CPL0_MASK);
|
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_movw_eflags_T0_cpl0(void)
|
void OPPROTO op_movw_eflags_T0_cpl0(void)
|
||||||
{
|
{
|
||||||
load_eflags(T0, FL_UPDATE_CPL0_MASK & 0xffff);
|
load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK) & 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
@ -3540,10 +3540,18 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
|
||||||
gen_op_movw_eflags_T0_cpl0();
|
gen_op_movw_eflags_T0_cpl0();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (s->dflag) {
|
if (s->cpl <= s->iopl) {
|
||||||
gen_op_movl_eflags_T0();
|
if (s->dflag) {
|
||||||
|
gen_op_movl_eflags_T0_io();
|
||||||
|
} else {
|
||||||
|
gen_op_movw_eflags_T0_io();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
gen_op_movw_eflags_T0();
|
if (s->dflag) {
|
||||||
|
gen_op_movl_eflags_T0();
|
||||||
|
} else {
|
||||||
|
gen_op_movw_eflags_T0();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gen_pop_update(s);
|
gen_pop_update(s);
|
||||||
|
@ -4265,6 +4273,10 @@ static uint16_t opc_write_flags[NB_OPS] = {
|
||||||
[INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
|
[INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
|
||||||
[INDEX_op_movw_eflags_T0] = CC_OSZAPC,
|
[INDEX_op_movw_eflags_T0] = CC_OSZAPC,
|
||||||
[INDEX_op_movl_eflags_T0] = CC_OSZAPC,
|
[INDEX_op_movl_eflags_T0] = CC_OSZAPC,
|
||||||
|
[INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
|
||||||
|
[INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
|
||||||
|
[INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
|
||||||
|
[INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
|
||||||
[INDEX_op_clc] = CC_C,
|
[INDEX_op_clc] = CC_C,
|
||||||
[INDEX_op_stc] = CC_C,
|
[INDEX_op_stc] = CC_C,
|
||||||
[INDEX_op_cmc] = CC_C,
|
[INDEX_op_cmc] = CC_C,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue