This commit is contained in:
Stanislav Shwartsman 2010-06-21 05:35:45 +00:00
parent 63a984bf71
commit 8e94474e03
3 changed files with 72 additions and 109 deletions

View File

@ -1,5 +1,5 @@
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// $Id: call_far.cc,v 1.56 2010-04-02 18:24:27 sshwarts Exp $ // $Id: call_far.cc,v 1.57 2010-06-21 05:35:45 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (c) 2005-2009 Stanislav Shwartsman // Copyright (c) 2005-2009 Stanislav Shwartsman
@ -530,22 +530,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::call_gate64(bx_selector_t *gate_selector)
// if non-conforming code segment and DPL < CPL then // if non-conforming code segment and DPL < CPL then
if (IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && (cs_descriptor.dpl < CPL)) if (IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && (cs_descriptor.dpl < CPL))
{ {
Bit64u RSP_for_cpl_x;
BX_DEBUG(("CALL GATE TO MORE PRIVILEGE LEVEL")); BX_DEBUG(("CALL GATE TO MORE PRIVILEGE LEVEL"));
// get new RSP for new privilege level from TSS // get new RSP for new privilege level from TSS
RSP_for_cpl_x = get_RSP_from_TSS(cs_descriptor.dpl); Bit64u RSP_for_cpl_x = get_RSP_from_TSS(cs_descriptor.dpl);
Bit64u 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; Bit64u old_RSP = RSP;
if (! IsCanonical(RSP_for_cpl_x)) {
// #SS(selector) when changing priviledge level
BX_ERROR(("call_gate64: canonical address failure %08x%08x",
GET32H(RSP_for_cpl_x), GET32L(RSP_for_cpl_x)));
exception(BX_SS_EXCEPTION, old_SS & 0xfffc);
}
// push old stack long pointer onto new stack // push old stack long pointer onto new stack
write_new_stack_qword_64(RSP_for_cpl_x - 8, cs_descriptor.dpl, old_SS); write_new_stack_qword_64(RSP_for_cpl_x - 8, cs_descriptor.dpl, old_SS);
write_new_stack_qword_64(RSP_for_cpl_x - 16, cs_descriptor.dpl, old_RSP); write_new_stack_qword_64(RSP_for_cpl_x - 16, cs_descriptor.dpl, old_RSP);

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: exception.cc,v 1.157 2010-04-14 17:33:19 sshwarts Exp $ // $Id: exception.cc,v 1.158 2010-06-21 05:35:45 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001-2010 The Bochs Project // Copyright (C) 2001-2010 The Bochs Project
@ -41,7 +41,7 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
bx_selector_t cs_selector; bx_selector_t cs_selector;
// interrupt vector must be within IDT table limits, // interrupt vector must be within IDT table limits,
// else #GP(vector number*8 + 2 + EXT) // else #GP(vector*8 + 2 + EXT)
if ((vector*16 + 15) > BX_CPU_THIS_PTR idtr.limit) { if ((vector*16 + 15) > BX_CPU_THIS_PTR idtr.limit) {
BX_ERROR(("interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x%x", BX_CPU_THIS_PTR idtr.limit)); BX_ERROR(("interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x%x", BX_CPU_THIS_PTR idtr.limit));
exception(BX_GP_EXCEPTION, vector*8 + 2); exception(BX_GP_EXCEPTION, vector*8 + 2);
@ -52,7 +52,7 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
if (desctmp2 & BX_CONST64(0x00001F0000000000)) { if (desctmp2 & BX_CONST64(0x00001F0000000000)) {
BX_ERROR(("interrupt(long mode): IDT entry extended attributes DWORD4 TYPE != 0")); BX_ERROR(("interrupt(long mode): IDT entry extended attributes DWORD4 TYPE != 0"));
exception(BX_GP_EXCEPTION, vector*8+ 2); exception(BX_GP_EXCEPTION, vector*8 + 2);
} }
Bit32u dword1 = GET32L(desctmp1); Bit32u dword1 = GET32L(desctmp1);
@ -68,7 +68,7 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
} }
// descriptor AR byte must indicate interrupt gate, trap gate, // descriptor AR byte must indicate interrupt gate, trap gate,
// or task gate, else #GP(vector*16 + 2 + EXT) // or task gate, else #GP(vector*8 + 2 + EXT)
if (gate_descriptor.type != BX_386_INTERRUPT_GATE && if (gate_descriptor.type != BX_386_INTERRUPT_GATE &&
gate_descriptor.type != BX_386_TRAP_GATE) gate_descriptor.type != BX_386_TRAP_GATE)
{ {
@ -78,14 +78,14 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
} }
// if software interrupt, then gate descripor DPL must be >= CPL, // if software interrupt, then gate descripor DPL must be >= CPL,
// else #GP(vector * 16 + 2 + EXT) // else #GP(vector * 8 + 2 + EXT)
if (soft_int && gate_descriptor.dpl < CPL) if (soft_int && gate_descriptor.dpl < CPL)
{ {
BX_ERROR(("interrupt(long mode): soft_int && gate.dpl < CPL")); BX_ERROR(("interrupt(long mode): soft_int && gate.dpl < CPL"));
exception(BX_GP_EXCEPTION, vector*8 + 2); exception(BX_GP_EXCEPTION, vector*8 + 2);
} }
// Gate must be present, else #NP(vector * 16 + 2 + EXT) // Gate must be present, else #NP(vector * 8 + 2 + EXT)
if (! IS_PRESENT(gate_descriptor)) { if (! IS_PRESENT(gate_descriptor)) {
BX_ERROR(("interrupt(long mode): gate.p == 0")); BX_ERROR(("interrupt(long mode): gate.p == 0"));
exception(BX_NP_EXCEPTION, vector*8 + 2); exception(BX_NP_EXCEPTION, vector*8 + 2);
@ -115,7 +115,7 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
// and code segment descriptor DPL<=CPL, else #GP(selector+EXT) // and code segment descriptor DPL<=CPL, else #GP(selector+EXT)
if (cs_descriptor.valid==0 || cs_descriptor.segment==0 || if (cs_descriptor.valid==0 || cs_descriptor.segment==0 ||
IS_DATA_SEGMENT(cs_descriptor.type) || IS_DATA_SEGMENT(cs_descriptor.type) ||
cs_descriptor.dpl>CPL) cs_descriptor.dpl > CPL)
{ {
BX_ERROR(("interrupt(long mode): not accessible or not code segment")); BX_ERROR(("interrupt(long mode): not accessible or not code segment"));
exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc); exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc);
@ -134,16 +134,21 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
exception(BX_NP_EXCEPTION, cs_selector.value & 0xfffc); exception(BX_NP_EXCEPTION, cs_selector.value & 0xfffc);
} }
Bit64u RSP_for_cpl_x;
Bit64u old_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;
Bit64u old_RIP = RIP;
Bit64u old_SS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value;
Bit64u old_RSP = RSP;
// if code segment is non-conforming and DPL < CPL then // if code segment is non-conforming and DPL < CPL then
// INTERRUPT TO INNER PRIVILEGE: // INTERRUPT TO INNER PRIVILEGE:
if (IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && cs_descriptor.dpl<CPL) if (IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && cs_descriptor.dpl < CPL)
{ {
Bit64u RSP_for_cpl_x;
BX_DEBUG(("interrupt(long mode): INTERRUPT TO INNER PRIVILEGE")); BX_DEBUG(("interrupt(long mode): INTERRUPT TO INNER PRIVILEGE"));
// check selector and descriptor for new stack in current TSS // check selector and descriptor for new stack in current TSS
if (ist != 0) { if (ist > 0) {
BX_DEBUG(("interrupt(long mode): trap to IST, vector = %d", ist)); BX_DEBUG(("interrupt(long mode): trap to IST, vector = %d", ist));
RSP_for_cpl_x = get_RSP_from_TSS(ist+3); RSP_for_cpl_x = get_RSP_from_TSS(ist+3);
} }
@ -151,20 +156,9 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
RSP_for_cpl_x = get_RSP_from_TSS(cs_descriptor.dpl); RSP_for_cpl_x = get_RSP_from_TSS(cs_descriptor.dpl);
} }
// align stack
RSP_for_cpl_x &= BX_CONST64(0xfffffffffffffff0); RSP_for_cpl_x &= BX_CONST64(0xfffffffffffffff0);
Bit64u old_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;
Bit64u old_RIP = RIP;
Bit64u old_SS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value;
Bit64u old_RSP = RSP;
if (! IsCanonical(RSP_for_cpl_x)) {
// #SS(selector) when changing priviledge level
BX_ERROR(("interrupt(long mode): canonical address failure %08x%08x",
GET32H(RSP_for_cpl_x), GET32L(RSP_for_cpl_x)));
exception(BX_SS_EXCEPTION, old_SS & 0xfffc);
}
// push old stack long pointer onto new stack // push old stack long pointer onto new stack
write_new_stack_qword_64(RSP_for_cpl_x - 8, cs_descriptor.dpl, old_SS); write_new_stack_qword_64(RSP_for_cpl_x - 8, cs_descriptor.dpl, old_SS);
write_new_stack_qword_64(RSP_for_cpl_x - 16, cs_descriptor.dpl, old_RSP); write_new_stack_qword_64(RSP_for_cpl_x - 16, cs_descriptor.dpl, old_RSP);
@ -184,72 +178,60 @@ void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error
// set up null SS descriptor // set up null SS descriptor
load_null_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], cs_descriptor.dpl); load_null_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], cs_descriptor.dpl);
RSP = RSP_for_cpl_x;
// if INTERRUPT GATE set IF to 0
if (!(gate_descriptor.type & 1)) // even is int-gate
BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_TF();
BX_CPU_THIS_PTR clear_VM();
BX_CPU_THIS_PTR clear_RF();
BX_CPU_THIS_PTR clear_NT();
return;
} }
else if(IS_CODE_SEGMENT_CONFORMING(cs_descriptor.type) || cs_descriptor.dpl==CPL)
// if code segment is conforming OR code segment DPL = CPL then
// INTERRUPT TO SAME PRIVILEGE LEVEL:
if (IS_CODE_SEGMENT_CONFORMING(cs_descriptor.type) || cs_descriptor.dpl==CPL)
{ {
BX_DEBUG(("interrupt(long mode): INTERRUPT TO SAME PRIVILEGE")); // if code segment is conforming OR code segment DPL = CPL then
// INTERRUPT TO SAME PRIVILEGE LEVEL:
Bit64u old_RSP = RSP, temp_RSP = RSP; BX_DEBUG(("interrupt(long mode): INTERRUPT TO SAME PRIVILEGE"));
// check selector and descriptor for new stack in current TSS // check selector and descriptor for new stack in current TSS
if (ist > 0) { if (ist > 0) {
BX_DEBUG(("interrupt(long mode): trap to IST, vector = %d", ist)); BX_DEBUG(("interrupt(long mode): trap to IST, vector = %d", ist));
temp_RSP = get_RSP_from_TSS(ist+3); RSP_for_cpl_x = get_RSP_from_TSS(ist+3);
}
else {
RSP_for_cpl_x = RSP;
} }
// align stack // align stack
temp_RSP &= BX_CONST64(0xfffffffffffffff0); RSP_for_cpl_x &= BX_CONST64(0xfffffffffffffff0);
// push flags onto stack // push flags onto stack
// push current CS selector onto stack // push current CS selector onto stack
// push return offset onto stack // push return offset onto stack
write_new_stack_qword_64(temp_RSP - 8, cs_descriptor.dpl, write_new_stack_qword_64(RSP_for_cpl_x - 8, cs_descriptor.dpl, old_SS);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value); write_new_stack_qword_64(RSP_for_cpl_x - 16, cs_descriptor.dpl, old_RSP);
write_new_stack_qword_64(temp_RSP - 16, cs_descriptor.dpl, old_RSP); write_new_stack_qword_64(RSP_for_cpl_x - 24, cs_descriptor.dpl, read_eflags());
write_new_stack_qword_64(temp_RSP - 24, cs_descriptor.dpl, read_eflags()); // push long pointer to return address onto new stack
write_new_stack_qword_64(temp_RSP - 32, cs_descriptor.dpl, write_new_stack_qword_64(RSP_for_cpl_x - 32, cs_descriptor.dpl, old_CS);
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); write_new_stack_qword_64(RSP_for_cpl_x - 40, cs_descriptor.dpl, old_RIP);
write_new_stack_qword_64(temp_RSP - 40, cs_descriptor.dpl, RIP); RSP_for_cpl_x -= 40;
temp_RSP -= 40;
if (push_error) { if (push_error) {
temp_RSP -= 8; RSP_for_cpl_x -= 8;
write_new_stack_qword_64(temp_RSP, cs_descriptor.dpl, error_code); write_new_stack_qword_64(RSP_for_cpl_x, cs_descriptor.dpl, error_code);
} }
// set the RPL field of CS to CPL // set the RPL field of CS to CPL
branch_far64(&cs_selector, &cs_descriptor, gate_dest_offset, CPL); branch_far64(&cs_selector, &cs_descriptor, gate_dest_offset, CPL);
}
RSP = temp_RSP; else {
BX_ERROR(("interrupt(long mode): bad descriptor type %u (CS.DPL=%u CPL=%u)",
// if interrupt gate then set IF to 0 (unsigned) cs_descriptor.type, (unsigned) cs_descriptor.dpl, (unsigned) CPL));
if (!(gate_descriptor.type & 1)) // even is int-gate exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc);
BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_TF();
BX_CPU_THIS_PTR clear_VM();
BX_CPU_THIS_PTR clear_RF();
BX_CPU_THIS_PTR clear_NT();
return;
} }
// else #GP(CS selector + ext) RSP = RSP_for_cpl_x;
BX_ERROR(("interrupt(long mode): bad descriptor type=%u, descriptor.dpl=%u, CPL=%u",
(unsigned) cs_descriptor.type, (unsigned) cs_descriptor.dpl, (unsigned) CPL)); // if interrupt gate then set IF to 0
BX_ERROR(("cs.segment = %u", (unsigned) cs_descriptor.segment)); if (!(gate_descriptor.type & 1)) // even is int-gate
exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc); BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_TF();
//BX_CPU_THIS_PTR clear_VM(); // VM is clear in long mode
BX_CPU_THIS_PTR clear_RF();
BX_CPU_THIS_PTR clear_NT();
} }
#endif #endif
@ -266,7 +248,7 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_
Bit32u gate_dest_offset; Bit32u gate_dest_offset;
// interrupt vector must be within IDT table limits, // interrupt vector must be within IDT table limits,
// else #GP(vector number*8 + 2 + EXT) // else #GP(vector*8 + 2 + EXT)
if ((vector*8 + 7) > BX_CPU_THIS_PTR idtr.limit) { if ((vector*8 + 7) > BX_CPU_THIS_PTR idtr.limit) {
BX_ERROR(("interrupt(): vector must be within IDT table limits, IDT.limit = 0x%x", BX_CPU_THIS_PTR idtr.limit)); BX_ERROR(("interrupt(): vector must be within IDT table limits, IDT.limit = 0x%x", BX_CPU_THIS_PTR idtr.limit));
exception(BX_GP_EXCEPTION, vector*8 + 2); exception(BX_GP_EXCEPTION, vector*8 + 2);
@ -402,7 +384,7 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_
// and code segment descriptor DPL<=CPL, else #GP(selector+EXT) // and code segment descriptor DPL<=CPL, else #GP(selector+EXT)
if (cs_descriptor.valid==0 || cs_descriptor.segment==0 || if (cs_descriptor.valid==0 || cs_descriptor.segment==0 ||
IS_DATA_SEGMENT(cs_descriptor.type) || IS_DATA_SEGMENT(cs_descriptor.type) ||
cs_descriptor.dpl>CPL) cs_descriptor.dpl > CPL)
{ {
BX_ERROR(("interrupt(): not accessible or not code segment cs=0x%04x", cs_selector.value)); BX_ERROR(("interrupt(): not accessible or not code segment cs=0x%04x", cs_selector.value));
exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc); exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc);
@ -414,14 +396,9 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_
exception(BX_NP_EXCEPTION, cs_selector.value & 0xfffc); exception(BX_NP_EXCEPTION, cs_selector.value & 0xfffc);
} }
if (cs_descriptor.dpl > CPL) {
BX_ERROR(("interrupt(): code segment DPL(%d) > CPL", cs_descriptor.dpl));
exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc);
}
// if code segment is non-conforming and DPL < CPL then // if code segment is non-conforming and DPL < CPL then
// INTERRUPT TO INNER PRIVILEGE // INTERRUPT TO INNER PRIVILEGE
if(IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && (cs_descriptor.dpl < CPL)) if(IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && cs_descriptor.dpl < CPL)
{ {
Bit16u old_SS, old_CS, SS_for_cpl_x; Bit16u old_SS, old_CS, SS_for_cpl_x;
Bit32u ESP_for_cpl_x, old_EIP, old_ESP; Bit32u ESP_for_cpl_x, old_EIP, old_ESP;
@ -633,16 +610,6 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_
// load new SS:eSP values from TSS // load new SS:eSP values from TSS
load_ss(&ss_selector, &ss_descriptor, cs_descriptor.dpl); load_ss(&ss_selector, &ss_descriptor, cs_descriptor.dpl);
EIP = gate_dest_offset;
// if INTERRUPT GATE set IF to 0
if (!(gate_descriptor.type & 1)) // even is int-gate
BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_TF();
BX_CPU_THIS_PTR clear_VM();
BX_CPU_THIS_PTR clear_RF();
BX_CPU_THIS_PTR clear_NT();
if (is_v8086_mode) if (is_v8086_mode)
{ {
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.valid = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.valid = 0;
@ -654,8 +621,6 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.valid = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.valid = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value = 0;
} }
return;
} }
else else
{ {
@ -695,18 +660,19 @@ void BX_CPU_C::protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_
// load CS descriptor // load CS descriptor
// set the RPL field of CS to CPL // set the RPL field of CS to CPL
load_cs(&cs_selector, &cs_descriptor, CPL); load_cs(&cs_selector, &cs_descriptor, CPL);
EIP = gate_dest_offset;
// if interrupt gate then set IF to 0
if (!(gate_descriptor.type & 1)) // even is int-gate
BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_TF();
BX_CPU_THIS_PTR clear_NT();
BX_CPU_THIS_PTR clear_VM();
BX_CPU_THIS_PTR clear_RF();
return;
} }
EIP = gate_dest_offset;
// if interrupt gate then set IF to 0
if (!(gate_descriptor.type & 1)) // even is int-gate
BX_CPU_THIS_PTR clear_IF();
BX_CPU_THIS_PTR clear_TF();
BX_CPU_THIS_PTR clear_NT();
BX_CPU_THIS_PTR clear_VM();
BX_CPU_THIS_PTR clear_RF();
return;
default: default:
BX_PANIC(("bad descriptor type in interrupt()!")); BX_PANIC(("bad descriptor type in interrupt()!"));
break; break;

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: tasking.cc,v 1.95 2010-06-18 14:24:45 sshwarts Exp $ // $Id: tasking.cc,v 1.96 2010-06-21 05:35:45 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001-2010 The Bochs Project // Copyright (C) 2001-2010 The Bochs Project
@ -784,6 +784,12 @@ Bit64u BX_CPU_C::get_RSP_from_TSS(unsigned pl)
} }
Bit64u rsp = system_read_qword(BX_CPU_THIS_PTR tr.cache.u.segment.base + TSSstackaddr); Bit64u rsp = system_read_qword(BX_CPU_THIS_PTR tr.cache.u.segment.base + TSSstackaddr);
if (! IsCanonical(rsp)) {
BX_ERROR(("get_RSP_from_TSS: canonical address failure 0x%08x%08x", GET32H(rsp), GET32L(rsp)));
exception(BX_SS_EXCEPTION, BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value & 0xfffc);
}
return rsp; return rsp;
} }
#endif // #if BX_SUPPORT_X86_64 #endif // #if BX_SUPPORT_X86_64