419 |
/* load all registers without an exception, then reload them with |
/* load all registers without an exception, then reload them with |
420 |
possible exception */ |
possible exception */ |
421 |
env->eip = new_eip; |
env->eip = new_eip; |
422 |
eflags_mask = FL_UPDATE_CPL0_MASK; |
eflags_mask = TF_MASK | AC_MASK | ID_MASK | |
423 |
|
IF_MASK | IOPL_MASK | VM_MASK | RF_MASK; |
424 |
if (!(type & 8)) |
if (!(type & 8)) |
425 |
eflags_mask &= 0xffff; |
eflags_mask &= 0xffff; |
426 |
load_eflags(new_eflags, eflags_mask); |
load_eflags(new_eflags, eflags_mask); |
576 |
uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2; |
uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2; |
577 |
uint32_t old_eip; |
uint32_t old_eip; |
578 |
|
|
|
#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 |
|
|
|
|
579 |
has_error_code = 0; |
has_error_code = 0; |
580 |
if (!is_int && !is_hw) { |
if (!is_int && !is_hw) { |
581 |
switch(intno) { |
switch(intno) { |
755 |
|
|
756 |
/* real mode interrupt */ |
/* real mode interrupt */ |
757 |
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, |
758 |
unsigned int next_eip) |
unsigned int next_eip) |
759 |
{ |
{ |
760 |
SegmentCache *dt; |
SegmentCache *dt; |
761 |
uint8_t *ptr, *ssp; |
uint8_t *ptr, *ssp; |
824 |
void do_interrupt(int intno, int is_int, int error_code, |
void do_interrupt(int intno, int is_int, int error_code, |
825 |
unsigned int next_eip, int is_hw) |
unsigned int next_eip, int is_hw) |
826 |
{ |
{ |
827 |
|
#ifdef DEBUG_PCALL |
828 |
|
if (loglevel) { |
829 |
|
static int count; |
830 |
|
fprintf(logfile, "%d: interrupt: vector=%02x error_code=%04x int=%d\n", |
831 |
|
count, intno, error_code, is_int); |
832 |
|
cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP); |
833 |
|
#if 0 |
834 |
|
{ |
835 |
|
int i; |
836 |
|
uint8_t *ptr; |
837 |
|
printf(" code="); |
838 |
|
ptr = env->segs[R_CS].base + env->eip; |
839 |
|
for(i = 0; i < 16; i++) { |
840 |
|
printf(" %02x", ldub(ptr + i)); |
841 |
|
} |
842 |
|
printf("\n"); |
843 |
|
} |
844 |
|
#endif |
845 |
|
count++; |
846 |
|
} |
847 |
|
#endif |
848 |
if (env->cr[0] & CR0_PE_MASK) { |
if (env->cr[0] & CR0_PE_MASK) { |
849 |
do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); |
do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); |
850 |
} else { |
} else { |
1294 |
if (loglevel) { |
if (loglevel) { |
1295 |
fprintf(logfile, "lcall %04x:%08x\n", |
fprintf(logfile, "lcall %04x:%08x\n", |
1296 |
new_cs, new_eip); |
new_cs, new_eip); |
1297 |
|
cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP); |
1298 |
} |
} |
1299 |
#endif |
#endif |
1300 |
if ((new_cs & 0xfffc) == 0) |
if ((new_cs & 0xfffc) == 0) |
1495 |
POPW(ssp, sp, sp_mask, new_cs); |
POPW(ssp, sp, sp_mask, new_cs); |
1496 |
POPW(ssp, sp, sp_mask, new_eflags); |
POPW(ssp, sp, sp_mask, new_eflags); |
1497 |
} |
} |
1498 |
ESP = (ESP & ~sp_mask) | (sp & 0xffff); |
ESP = (ESP & ~sp_mask) | (sp & sp_mask); |
1499 |
load_seg_vm(R_CS, new_cs); |
load_seg_vm(R_CS, new_cs); |
1500 |
env->eip = new_eip; |
env->eip = new_eip; |
1501 |
if (env->eflags & VM_MASK) |
if (env->eflags & VM_MASK) |
1502 |
eflags_mask = FL_UPDATE_MASK32 | IF_MASK | RF_MASK; |
eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK; |
1503 |
else |
else |
1504 |
eflags_mask = FL_UPDATE_CPL0_MASK; |
eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK; |
1505 |
if (shift == 0) |
if (shift == 0) |
1506 |
eflags_mask &= 0xffff; |
eflags_mask &= 0xffff; |
1507 |
load_eflags(new_eflags, eflags_mask); |
load_eflags(new_eflags, eflags_mask); |
1513 |
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; |
1514 |
uint32_t new_es, new_ds, new_fs, new_gs; |
uint32_t new_es, new_ds, new_fs, new_gs; |
1515 |
uint32_t e1, e2, ss_e1, ss_e2; |
uint32_t e1, e2, ss_e1, ss_e2; |
1516 |
int cpl, dpl, rpl, eflags_mask; |
int cpl, dpl, rpl, eflags_mask, iopl; |
1517 |
uint8_t *ssp; |
uint8_t *ssp; |
1518 |
|
|
1519 |
sp_mask = get_sp_mask(env->segs[R_SS].flags); |
sp_mask = get_sp_mask(env->segs[R_SS].flags); |
1538 |
} |
} |
1539 |
#ifdef DEBUG_PCALL |
#ifdef DEBUG_PCALL |
1540 |
if (loglevel) { |
if (loglevel) { |
1541 |
fprintf(logfile, "lret new %04x:%08x\n", |
fprintf(logfile, "lret new %04x:%08x addend=0x%x\n", |
1542 |
new_cs, new_eip); |
new_cs, new_eip, addend); |
1543 |
|
cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP); |
1544 |
} |
} |
1545 |
#endif |
#endif |
1546 |
if ((new_cs & 0xfffc) == 0) |
if ((new_cs & 0xfffc) == 0) |
1614 |
ESP = (ESP & ~sp_mask) | (sp & sp_mask); |
ESP = (ESP & ~sp_mask) | (sp & sp_mask); |
1615 |
env->eip = new_eip; |
env->eip = new_eip; |
1616 |
if (is_iret) { |
if (is_iret) { |
1617 |
/* NOTE: 'cpl' can be different from the current CPL */ |
/* NOTE: 'cpl' is the _old_ CPL */ |
1618 |
|
eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK; |
1619 |
if (cpl == 0) |
if (cpl == 0) |
1620 |
eflags_mask = FL_UPDATE_CPL0_MASK; |
eflags_mask |= IOPL_MASK; |
1621 |
else |
iopl = (env->eflags >> IOPL_SHIFT) & 3; |
1622 |
eflags_mask = FL_UPDATE_MASK32; |
if (cpl <= iopl) |
1623 |
|
eflags_mask |= IF_MASK; |
1624 |
if (shift == 0) |
if (shift == 0) |
1625 |
eflags_mask &= 0xffff; |
eflags_mask &= 0xffff; |
1626 |
load_eflags(new_eflags, eflags_mask); |
load_eflags(new_eflags, eflags_mask); |
1636 |
POPL(ssp, sp, sp_mask, new_gs); |
POPL(ssp, sp, sp_mask, new_gs); |
1637 |
|
|
1638 |
/* modify processor state */ |
/* modify processor state */ |
1639 |
load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK); |
load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK | |
1640 |
|
IF_MASK | IOPL_MASK | VM_MASK | VIF_MASK | VIP_MASK); |
1641 |
load_seg_vm(R_CS, new_cs & 0xffff); |
load_seg_vm(R_CS, new_cs & 0xffff); |
1642 |
cpu_x86_set_cpl(env, 3); |
cpu_x86_set_cpl(env, 3); |
1643 |
load_seg_vm(R_SS, new_ss & 0xffff); |
load_seg_vm(R_SS, new_ss & 0xffff); |