exception was suffering from the same issue - fixed with new_stack push functtions

This commit is contained in:
Stanislav Shwartsman 2007-10-19 10:59:39 +00:00
parent 14b4f66d4e
commit 0f3fdaf94b
2 changed files with 93 additions and 65 deletions

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////////
// $Id: call_far.cc,v 1.18 2007-10-19 10:14:33 sshwarts Exp $
// $Id: call_far.cc,v 1.19 2007-10-19 10:59:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -372,7 +372,7 @@ BX_CPU_C::call_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp)
bx_segment_reg_t new_stack;
new_stack.selector = ss_selector;
new_stack.cache = ss_descriptor;
new_stack.selector.rpl = ss_descriptor.dpl;
new_stack.selector.rpl = cs_descriptor.dpl;
// add cpl to the selector value
new_stack.selector.value = (0xfffc & new_stack.selector.value) |
new_stack.selector.rpl;
@ -415,7 +415,7 @@ BX_CPU_C::call_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp)
/* load new SS:SP value from TSS */
/* load SS descriptor */
load_ss(&ss_selector, &ss_descriptor, ss_descriptor.dpl);
load_ss(&ss_selector, &ss_descriptor, cs_descriptor.dpl);
if (ss_descriptor.u.segment.d_b)
ESP = temp_ESP;
else

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: exception.cc,v 1.92 2007-10-19 10:14:33 sshwarts Exp $
// $Id: exception.cc,v 1.93 2007-10-19 10:59:39 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -185,11 +185,25 @@ void BX_CPU_C::long_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error_code
exception(BX_GP_EXCEPTION, 0, 0);
}
Bit16u old_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;
Bit64u old_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;
Bit64u old_RIP = RIP;
Bit16u old_SS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value;
Bit64u old_SS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value;
Bit64u old_RSP = RSP;
// push old stack long pointer onto new stack
write_new_stack_qword(RSP_for_cpl_x - 8, old_SS);
write_new_stack_qword(RSP_for_cpl_x - 16, old_RSP);
write_new_stack_qword(RSP_for_cpl_x - 24, read_eflags());
// push long pointer to return address onto new stack
write_new_stack_qword(RSP_for_cpl_x - 32, old_CS);
write_new_stack_qword(RSP_for_cpl_x - 40, old_RIP);
RSP_for_cpl_x -= 40;
if (is_error_code) {
RSP_for_cpl_x -= 8;
write_new_stack_qword(RSP_for_cpl_x, error_code);
}
bx_selector_t ss_selector;
bx_descriptor_t ss_descriptor;
@ -204,16 +218,6 @@ void BX_CPU_C::long_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error_code
load_ss(&ss_selector, &ss_descriptor, cs_descriptor.dpl);
RSP = RSP_for_cpl_x;
// push old stack long pointer onto new stack
push_64(old_SS);
push_64(old_RSP);
push_64(read_eflags());
// push long pointer to return address onto new stack
push_64(old_CS);
push_64(old_RIP);
if (is_error_code)
push_64(error_code);
// if INTERRUPT GATE set IF to 0
if (!(gate_descriptor.type & 1)) // even is int-gate
BX_CPU_THIS_PTR clear_IF();
@ -286,6 +290,7 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error
Bit16u gate_dest_selector;
Bit32u gate_dest_offset;
Bit32u temp_ESP;
// interrupt vector must be within IDT table limits,
// else #GP(vector number*8 + 2 + EXT)
@ -544,13 +549,83 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error
old_EIP = EIP;
old_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;
// Prepare new stack segment
bx_segment_reg_t new_stack;
new_stack.selector = ss_selector;
new_stack.cache = ss_descriptor;
new_stack.selector.rpl = cs_descriptor.dpl;
// add cpl to the selector value
new_stack.selector.value = (0xfffc & new_stack.selector.value) |
new_stack.selector.rpl;
bx_bool user = (cs_descriptor.dpl == 3);
if (ss_descriptor.u.segment.d_b)
temp_ESP = ESP_for_cpl_x;
else
temp_ESP = (Bit16u) ESP_for_cpl_x;
if (is_v8086_mode)
{
if (gate_descriptor.type>=14) { // 386 int/trap gate
write_new_stack_dword(&new_stack, temp_ESP-4, user,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value);
write_new_stack_dword(&new_stack, temp_ESP-8, user,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value);
write_new_stack_dword(&new_stack, temp_ESP-12, user,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value);
write_new_stack_dword(&new_stack, temp_ESP-16, user,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value);
temp_ESP -= 16;
}
else {
write_new_stack_word(&new_stack, temp_ESP-2, user,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value);
write_new_stack_word(&new_stack, temp_ESP-4, user,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value);
write_new_stack_word(&new_stack, temp_ESP-6, user,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value);
write_new_stack_word(&new_stack, temp_ESP-8, user,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value);
temp_ESP -= 8;
}
}
if (gate_descriptor.type>=14) { // 386 int/trap gate
// push long pointer to old stack onto new stack
write_new_stack_dword(&new_stack, temp_ESP-4, user, old_SS);
write_new_stack_dword(&new_stack, temp_ESP-8, user, old_ESP);
write_new_stack_dword(&new_stack, temp_ESP-12, user, read_eflags());
write_new_stack_dword(&new_stack, temp_ESP-16, user, old_CS);
write_new_stack_dword(&new_stack, temp_ESP-20, user, old_EIP);
temp_ESP -= 20;
if (is_error_code) {
temp_ESP -= 4;
write_new_stack_dword(&new_stack, temp_ESP, user, error_code);
}
}
else { // 286 int/trap gate
// push long pointer to old stack onto new stack
write_new_stack_word(&new_stack, temp_ESP-2, user, old_SS);
write_new_stack_word(&new_stack, temp_ESP-4, user, (Bit16u) old_ESP);
write_new_stack_word(&new_stack, temp_ESP-6, user, read_flags());
write_new_stack_word(&new_stack, temp_ESP-8, user, old_CS);
write_new_stack_word(&new_stack, temp_ESP-10, user, (Bit16u) old_EIP);
temp_ESP -= 10;
if (is_error_code) {
temp_ESP -= 2;
write_new_stack_word(&new_stack, temp_ESP, user, error_code);
}
}
// load new SS:SP values from TSS
load_ss(&ss_selector, &ss_descriptor, cs_descriptor.dpl);
if (ss_descriptor.u.segment.d_b)
ESP = ESP_for_cpl_x;
ESP = temp_ESP;
else
SP = ESP_for_cpl_x; // leave upper 16bits
SP = (Bit16u) temp_ESP;
// load new CS:IP values from gate
// set CPL to new code segment DPL
@ -558,8 +633,6 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error
load_cs(&cs_selector, &cs_descriptor, cs_descriptor.dpl);
EIP = gate_dest_offset;
Bit32u eflags = read_eflags();
// if INTERRUPT GATE set IF to 0
if (!(gate_descriptor.type & 1)) // even is int-gate
BX_CPU_THIS_PTR clear_IF();
@ -570,19 +643,6 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error
if (is_v8086_mode)
{
if (gate_descriptor.type>=14) { // 386 int/trap gate
push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value);
push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value);
push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value);
push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value);
}
else {
push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value);
push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value);
push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value);
push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value);
}
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.valid = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.valid = 0;
@ -593,37 +653,6 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value = 0;
}
if (gate_descriptor.type>=14) { // 386 int/trap gate
// push long pointer to old stack onto new stack
push_32(old_SS);
push_32(old_ESP);
// push EFLAGS
push_32(eflags);
// push long pointer to return address onto new stack
push_32(old_CS);
push_32(old_EIP);
if (is_error_code)
push_32(error_code);
}
else { // 286 int/trap gate
// push long pointer to old stack onto new stack
push_16(old_SS);
push_16(old_ESP); // ignores upper 16bits
// push FLAGS
push_16(eflags); // ignores upper 16bits
// push return address onto new stack
push_16(old_CS);
push_16(old_EIP); // ignores upper 16bits
if (is_error_code)
push_16(error_code);
}
return;
}
@ -638,7 +667,6 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, bx_bool is_INT, bx_bool is_error
if (IS_CODE_SEGMENT_CONFORMING(cs_descriptor.type) || cs_descriptor.dpl==CPL)
{
int bytes;
Bit32u temp_ESP;
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)
temp_ESP = ESP;