Fix code duplication in tas

This commit is contained in:
Stanislav Shwartsman 2005-08-28 17:37:37 +00:00
parent 246d89d6a3
commit 086ee4c9aa
4 changed files with 99 additions and 262 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.cc,v 1.110 2005-08-15 15:43:04 akrisak Exp $
// $Id: cpu.cc,v 1.111 2005-08-28 17:37:36 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -858,8 +858,7 @@ BX_CPU_THIS_PTR eipPageWindowSize = 0; // Fixme
#if BX_EXTERNAL_DEBUGGER
void
BX_CPU_C::ask (int level, const char *prefix, const char *fmt, va_list ap)
void BX_CPU_C::ask (int level, const char *prefix, const char *fmt, va_list ap)
{
char buf1[1024];
vsprintf (buf1, fmt, ap);
@ -867,8 +866,7 @@ BX_CPU_C::ask (int level, const char *prefix, const char *fmt, va_list ap)
trap_debugger(1);
}
void
BX_CPU_C::trap_debugger (bx_bool callnow)
void BX_CPU_C::trap_debugger (bx_bool callnow)
{
regs.debug_state = debug_step;
if (callnow) {
@ -882,10 +880,9 @@ BX_CPU_C::trap_debugger (bx_bool callnow)
#if BX_DEBUGGER
extern unsigned int dbg_show_mask;
bx_bool
BX_CPU_C::dbg_is_begin_instr_bpoint(Bit32u cs, Bit32u eip, Bit32u laddr,
Bit32u is_32)
{ Bit64u tt = bx_pc_system.time_ticks();
bx_bool BX_CPU_C::dbg_is_begin_instr_bpoint(Bit32u cs, Bit32u eip, Bit32u laddr, Bit32u is_32)
{
Bit64u tt = bx_pc_system.time_ticks();
//fprintf (stderr, "begin_instr_bp: checking cs:eip %04x:%08x\n", cs, eip);
BX_CPU_THIS_PTR guard_found.cs = cs;
@ -917,7 +914,8 @@ BX_CPU_C::dbg_is_begin_instr_bpoint(Bit32u cs, Bit32u eip, Bit32u laddr,
#if BX_DBG_SUPPORT_VIR_BPOINT
if (bx_guard.guard_for & BX_DBG_GUARD_IADDR_VIR) {
if ((BX_CPU_THIS_PTR guard_found.icount!=0) ||
(tt != BX_CPU_THIS_PTR guard_found.time_tick)) {
(tt != BX_CPU_THIS_PTR guard_found.time_tick))
{
for (unsigned i=0; i<bx_guard.iaddr.num_virtual; i++) {
if ( bx_guard.iaddr.vir[i].enabled &&
(bx_guard.iaddr.vir[i].cs == cs) &&
@ -934,7 +932,8 @@ BX_CPU_C::dbg_is_begin_instr_bpoint(Bit32u cs, Bit32u eip, Bit32u laddr,
#if BX_DBG_SUPPORT_LIN_BPOINT
if (bx_guard.guard_for & BX_DBG_GUARD_IADDR_LIN) {
if ((BX_CPU_THIS_PTR guard_found.icount!=0) ||
(tt != BX_CPU_THIS_PTR guard_found.time_tick)) {
(tt != BX_CPU_THIS_PTR guard_found.time_tick))
{
for (unsigned i=0; i<bx_guard.iaddr.num_linear; i++) {
if (bx_guard.iaddr.lin[i].enabled &&
(bx_guard.iaddr.lin[i].addr == BX_CPU_THIS_PTR guard_found.laddr) ) {
@ -958,12 +957,11 @@ BX_CPU_C::dbg_is_begin_instr_bpoint(Bit32u cs, Bit32u eip, Bit32u laddr,
// and once you get to a breakpoint you are stuck there forever.
// Not pretty.
if (valid && ((BX_CPU_THIS_PTR guard_found.icount!=0) ||
(tt != BX_CPU_THIS_PTR guard_found.time_tick))) {
(tt != BX_CPU_THIS_PTR guard_found.time_tick)))
{
for (unsigned i=0; i<bx_guard.iaddr.num_physical; i++) {
if ( bx_guard.iaddr.phy[i].enabled &&
(bx_guard.iaddr.phy[i].addr == phy) ) {
if (bx_guard.iaddr.phy[i].enabled && (bx_guard.iaddr.phy[i].addr == phy))
{
BX_CPU_THIS_PTR guard_found.guard_found = BX_DBG_GUARD_IADDR_PHY;
BX_CPU_THIS_PTR guard_found.iaddr_index = i;
BX_CPU_THIS_PTR guard_found.time_tick = tt;
@ -974,10 +972,10 @@ BX_CPU_C::dbg_is_begin_instr_bpoint(Bit32u cs, Bit32u eip, Bit32u laddr,
}
#endif
}
return(0); // not on a breakpoint
}
bx_bool
BX_CPU_C::dbg_is_end_instr_bpoint(Bit32u cs, Bit32u eip, Bit32u laddr,
Bit32u is_32)
@ -1019,9 +1017,7 @@ BX_CPU_C::dbg_is_end_instr_bpoint(Bit32u cs, Bit32u eip, Bit32u laddr,
return(0); // no breakpoint
}
void
BX_CPU_C::dbg_take_irq(void)
void BX_CPU_C::dbg_take_irq(void)
{
unsigned vector;
@ -1039,8 +1035,7 @@ BX_CPU_C::dbg_take_irq(void)
}
}
void
BX_CPU_C::dbg_force_interrupt(unsigned vector)
void BX_CPU_C::dbg_force_interrupt(unsigned vector)
{
// Used to force slave simulator to take an interrupt, without
// regard to IF
@ -1054,8 +1049,7 @@ BX_CPU_C::dbg_force_interrupt(unsigned vector)
}
}
void
BX_CPU_C::dbg_take_dma(void)
void BX_CPU_C::dbg_take_dma(void)
{
// NOTE: similar code in ::cpu_loop()
if ( BX_HRQ ) {

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.238 2005-08-23 20:01:54 sshwarts Exp $
// $Id: cpu.h,v 1.239 2005-08-28 17:37:36 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -2797,10 +2797,9 @@ public: // for now...
#endif
BX_SMF void init_v8086_mode(void);
BX_SMF void v8086_message(void);
BX_SMF void task_switch(bx_selector_t *selector,
bx_descriptor_t *descriptor,
unsigned source,
Bit32u dword1, Bit32u dword2);
BX_SMF void task_switch_load_selector(bx_segment_reg_t *seg, Bit16u raw_selector, Bit8u cs_rpl);
BX_SMF void task_switch(bx_selector_t *selector, bx_descriptor_t *descriptor,
unsigned source, Bit32u dword1, Bit32u dword2);
BX_SMF void get_SS_ESP_from_TSS(unsigned pl, Bit16u *ss, Bit32u *esp);
#if BX_SUPPORT_X86_64
BX_SMF void get_RSP_from_TSS(unsigned pl, Bit64u *rsp);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: stack_pro.cc,v 1.24 2005-07-31 17:57:27 sshwarts Exp $
// $Id: stack_pro.cc,v 1.25 2005-08-28 17:37:37 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -44,7 +44,7 @@ BX_CPU_C::push_16(Bit16u value16)
else
#endif
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { /* StackAddrSize = 32 */
write_virtual_word(BX_SEG_REG_SS, ESP-2, &value16);
write_virtual_word(BX_SEG_REG_SS, (Bit32u) (ESP-2), &value16);
ESP -= 2;
}
else
@ -69,7 +69,7 @@ void BX_CPU_C::push_32(Bit32u value32)
else
#endif
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { /* StackAddrSize = 32 */
write_virtual_dword(BX_SEG_REG_SS, ESP-4, &value32);
write_virtual_dword(BX_SEG_REG_SS, (Bit32u) (ESP-4), &value32);
ESP -= 4;
}
else
@ -93,7 +93,7 @@ void BX_CPU_C::push_64(Bit64u value64)
else
#endif
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { /* StackAddrSize = 32 */
write_virtual_qword(BX_SEG_REG_SS, ESP-8, &value64);
write_virtual_qword(BX_SEG_REG_SS, (Bit32u) (ESP-8), &value64);
ESP -= 8;
}
else
@ -223,7 +223,6 @@ BX_CPU_C::can_push(bx_descriptor_t *descriptor, Bit32u esp, Bit32u bytes)
return(0);
}
if (descriptor->u.segment.c_ed) { /* expand down segment */
Bit32u expand_down_limit;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: tasking.cc,v 1.23 2005-08-21 18:23:36 sshwarts Exp $
// $Id: tasking.cc,v 1.24 2005-08-28 17:37:37 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -138,14 +138,11 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
Bit16u temp16, trap_word;
bx_selector_t cs_selector, ss_selector, ds_selector, es_selector,
fs_selector, gs_selector, ldt_selector;
bx_descriptor_t cs_descriptor, ss_descriptor, ds_descriptor, es_descriptor,
fs_descriptor, gs_descriptor, ldt_descriptor;
bx_descriptor_t cs_descriptor, ss_descriptor, ldt_descriptor;
Bit32u old_TSS_max, new_TSS_max, old_TSS_limit, new_TSS_limit;
Bit32u newEAX, newECX, newEDX, newEBX;
Bit32u newESP, newEBP, newESI, newEDI;
Bit32u newEFLAGS, oldEFLAGS, newEIP;
unsigned exception_no;
Bit16u error_code;
BX_DEBUG(( "TASKING: ENTER" ));
@ -166,8 +163,8 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
// Privilege and busy checks done in CALL, JUMP, INT, IRET
exception_no = 256; // no exception
error_code = 0;
unsigned exception_no = 256; // no exception
Bit16u error_code = 0;
oldEFLAGS = read_eflags();
// Gather info about old TSS
@ -196,6 +193,11 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
new_TSS_limit = tss_descriptor->u.tss386.limit_scaled;
}
if (obase32 == nbase32)
{
BX_PANIC(("Task switching to the same TSS might be not implemented correctly !"));
}
// Task State Seg must be present, else #NP(TSS selector)
if (tss_descriptor->p==0) {
BX_ERROR(("task_switch: TSS.p == 0"));
@ -303,15 +305,6 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
// I/O Map Base Address ???
}
#if 0
if (ss_descriptor.u.segment.d_b && (tss_descriptor->type<9)) {
BX_DEBUG(( "++++++++++++++++++++++++++" ));
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = 0;
exception(BX_SS_EXCEPTION, raw_ss_selector & 0xfffc, 0);
//exception(BX_TS_EXCEPTION, tss_selector->value & 0xfffc, 0);
}
#endif
//
// Step 6: If JMP or IRET, clear busy bit in old task TSS descriptor,
// otherwise leave set.
@ -320,8 +313,7 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
// effect on Busy bit of old task
if ( (source==BX_TASK_FROM_JUMP) || (source==BX_TASK_FROM_IRET) ) {
// Bit is cleared
Bit32u laddr;
laddr = BX_CPU_THIS_PTR gdtr.base +
Bit32u laddr = BX_CPU_THIS_PTR gdtr.base +
(BX_CPU_THIS_PTR tr.selector.index<<3) + 4;
access_linear(laddr, 4, 0, BX_READ, &temp32);
temp32 &= ~0x00000200;
@ -427,8 +419,7 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
if ( (source==BX_TASK_FROM_JUMP) || (source==BX_TASK_FROM_CALL_OR_INT) ) {
// set the new task's busy bit
Bit32u laddr;
laddr = BX_CPU_THIS_PTR gdtr.base + (tss_selector->index<<3) + 4;
Bit32u laddr = BX_CPU_THIS_PTR gdtr.base + (tss_selector->index<<3) + 4;
access_linear(laddr, 4, 0, BX_READ, &dword2);
dword2 |= 0x00000200;
access_linear(laddr, 4, 0, BX_WRITE, &dword2);
@ -506,7 +497,6 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.valid = 0;
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.valid = 0;
// need to test valid bit in fetch_raw_descriptor?()
// or set limit to 0 instead when LDT is loaded with
// null. ??? +++
@ -569,6 +559,15 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
}
else {
// if new selector is not null then perform following checks:
// index must be within its descriptor table limits else #TS(selector)
// AR byte must indicate data or readable code else #TS(selector)
// if data or non-conforming code then:
// DPL must be >= CPL else #TS(selector)
// DPL must be >= RPL else #TS(selector)
// AR byte must indicate PRESENT else #NP(selector)
// load cache with new segment descriptor and set valid bit
// CS
if ( (raw_cs_selector & 0xfffc) != 0 ) {
bx_bool good = fetch_raw_descriptor2(&cs_selector, &dword1, &dword2);
@ -593,7 +592,7 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
// if non-conforming then DPL must equal selector RPL else #TS(CS)
if (cs_descriptor.u.segment.c_ed==0 &&
cs_descriptor.dpl!=cs_selector.rpl)
cs_descriptor.dpl!=cs_selector.rpl)
{
BX_INFO(("task_switch: non-conforming: CS.dpl!=CS.RPL"));
exception_no = BX_TS_EXCEPTION;
@ -645,8 +644,7 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
// SS selector must be within its descriptor table limits else #TS(SS)
// SS descriptor AR byte must must indicate writable data segment,
// else #TS(SS)
if (ss_descriptor.valid==0 ||
ss_descriptor.segment==0 ||
if (ss_descriptor.valid==0 || ss_descriptor.segment==0 ||
ss_descriptor.u.segment.executable ||
ss_descriptor.u.segment.r_w==0)
{
@ -657,7 +655,7 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
}
//
// Stack segment is present in memory, else #SF(new stack segment)
// Stack segment is present in memory, else #SS(new stack segment)
//
if (! IS_PRESENT(ss_descriptor)) {
BX_PANIC(("task_switch: SS not present"));
@ -682,15 +680,6 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
goto post_exception;
}
#if 0
if (ss_descriptor.u.segment.d_b && (tss_descriptor->type<9)) {
BX_DEBUG(( "++++++++++++++++++++++++++" ));
exception_no = BX_TS_EXCEPTION;
error_code = raw_ss_selector & 0xfffc;
goto post_exception;
}
#endif
// All checks pass, fill in shadow cache
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache = ss_descriptor;
}
@ -702,200 +691,14 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
goto post_exception;
}
// if new selector is not null then perform following checks:
// index must be within its descriptor table limits else #TS(selector)
// AR byte must indicate data or readable code else #TS(selector)
// if data or non-conforming code then:
// DPL must be >= CPL else #TS(selector)
// DPL must be >= RPL else #TS(selector)
// AR byte must indicate PRESENT else #NP(selector)
// load cache with new segment descriptor and set valid bit
// DS
if ( (raw_ds_selector & 0xfffc) != 0 ) {
bx_bool good = fetch_raw_descriptor2(&ds_selector, &dword1, &dword2);
if (!good) {
BX_INFO(("task_switch: bad DS fetch"));
exception_no = BX_TS_EXCEPTION;
error_code = raw_ds_selector & 0xfffc;
goto post_exception;
}
parse_descriptor(dword1, dword2, &ds_descriptor);
if (ds_descriptor.valid==0 || ds_descriptor.segment==0 ||
(ds_descriptor.u.segment.executable &&
ds_descriptor.u.segment.r_w==0))
{
BX_PANIC(("task_switch: DS not valid"));
exception_no = BX_TS_EXCEPTION;
error_code = raw_ds_selector & 0xfffc;
goto post_exception;
}
// if data or non-conforming code
if (ds_descriptor.type<12 &&
(ds_descriptor.dpl<cs_selector.rpl ||
ds_descriptor.dpl<ds_selector.rpl))
{
BX_PANIC(("task_switch: DS.dpl not valid"));
exception_no = BX_TS_EXCEPTION;
error_code = raw_ds_selector & 0xfffc;
goto post_exception;
}
if (! IS_PRESENT(ds_descriptor)) {
BX_PANIC(("task_switch: DS.p==0"));
exception_no = BX_NP_EXCEPTION;
error_code = raw_ds_selector & 0xfffc;
goto post_exception;
}
// All checks pass, fill in shadow cache
BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache = ds_descriptor;
}
else {
// NULL DS selector is OK, leave cache invalid
}
// ES
if ( (raw_es_selector & 0xfffc) != 0 ) {
bx_bool good = fetch_raw_descriptor2(&es_selector, &dword1, &dword2);
if (!good) {
BX_INFO(("task_switch: bad ES fetch"));
exception_no = BX_TS_EXCEPTION;
error_code = raw_es_selector & 0xfffc;
goto post_exception;
}
parse_descriptor(dword1, dword2, &es_descriptor);
if (es_descriptor.valid==0 || es_descriptor.segment==0 ||
(es_descriptor.u.segment.executable &&
es_descriptor.u.segment.r_w==0))
{
BX_PANIC(("task_switch: ES not valid"));
exception_no = BX_TS_EXCEPTION;
error_code = raw_es_selector & 0xfffc;
goto post_exception;
}
// if data or non-conforming code
if (es_descriptor.type<12 &&
(es_descriptor.dpl<cs_selector.rpl ||
es_descriptor.dpl<es_selector.rpl))
{
BX_PANIC(("task_switch: ES.dpl not valid"));
exception_no = BX_TS_EXCEPTION;
error_code = raw_es_selector & 0xfffc;
goto post_exception;
}
if (! IS_PRESENT(es_descriptor)) {
BX_PANIC(("task_switch: ES.p==0"));
exception_no = BX_NP_EXCEPTION;
error_code = raw_es_selector & 0xfffc;
goto post_exception;
}
// All checks pass, fill in shadow cache
BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache = es_descriptor;
}
else {
// NULL ES selector is OK, leave cache invalid
}
// FS
if ( (raw_fs_selector & 0xfffc) != 0 ) { // not NULL
bx_bool good = fetch_raw_descriptor2(&fs_selector, &dword1, &dword2);
if (!good) {
BX_INFO(("task_switch: bad FS fetch"));
exception_no = BX_TS_EXCEPTION;
error_code = raw_fs_selector & 0xfffc;
goto post_exception;
}
parse_descriptor(dword1, dword2, &fs_descriptor);
if (fs_descriptor.valid==0 || fs_descriptor.segment==0 ||
(fs_descriptor.u.segment.executable &&
fs_descriptor.u.segment.r_w==0))
{
BX_PANIC(("task_switch: FS not valid"));
exception_no = BX_TS_EXCEPTION;
error_code = raw_fs_selector & 0xfffc;
goto post_exception;
}
// if data or non-conforming code
if (fs_descriptor.type<12 &&
(fs_descriptor.dpl<cs_selector.rpl ||
fs_descriptor.dpl<fs_selector.rpl))
{
BX_PANIC(("task_switch: FS.dpl not valid"));
exception_no = BX_TS_EXCEPTION;
error_code = raw_fs_selector & 0xfffc;
goto post_exception;
}
if (! IS_PRESENT(fs_descriptor)) {
BX_PANIC(("task_switch: FS.p==0"));
exception_no = BX_NP_EXCEPTION;
error_code = raw_fs_selector & 0xfffc;
goto post_exception;
}
// All checks pass, fill in shadow cache
BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache = fs_descriptor;
}
else {
// NULL FS selector is OK, leave cache invalid
}
// GS
if ( (raw_gs_selector & 0xfffc) != 0 ) {
bx_bool good = fetch_raw_descriptor2(&gs_selector, &dword1, &dword2);
if (!good) {
BX_INFO(("task_switch: bad GS fetch"));
exception_no = BX_TS_EXCEPTION;
error_code = raw_gs_selector & 0xfffc;
goto post_exception;
}
parse_descriptor(dword1, dword2, &gs_descriptor);
if (gs_descriptor.valid==0 || gs_descriptor.segment==0 ||
(gs_descriptor.u.segment.executable &&
gs_descriptor.u.segment.r_w==0))
{
BX_PANIC(("task_switch: GS not valid"));
exception_no = BX_TS_EXCEPTION;
error_code = raw_gs_selector & 0xfffc;
goto post_exception;
}
// if data or non-conforming code
if (gs_descriptor.type<12 &&
(gs_descriptor.dpl<cs_selector.rpl ||
gs_descriptor.dpl<gs_selector.rpl))
{
BX_PANIC(("task_switch: GS.dpl not valid"));
exception_no = BX_TS_EXCEPTION;
error_code = raw_gs_selector & 0xfffc;
goto post_exception;
}
if (! IS_PRESENT(gs_descriptor)) {
BX_PANIC(("task_switch: GS.p==0"));
exception_no = BX_NP_EXCEPTION;
error_code = raw_gs_selector & 0xfffc;
goto post_exception;
}
// All checks pass, fill in shadow cache
BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache = gs_descriptor;
}
else {
// NULL GS selector is OK, leave cache invalid
}
task_switch_load_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS],
raw_ds_selector, cs_selector.rpl);
task_switch_load_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES],
raw_es_selector, cs_selector.rpl);
task_switch_load_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS],
raw_fs_selector, cs_selector.rpl);
task_switch_load_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS],
raw_gs_selector, cs_selector.rpl);
}
if ((tss_descriptor->type>=9) && (trap_word & 0x0001)) {
@ -917,6 +720,48 @@ post_exception:
exception(exception_no, error_code, 0);
}
void BX_CPU_C::task_switch_load_selector(bx_segment_reg_t *seg, Bit16u raw_selector, Bit8u cs_rpl)
{
bx_selector_t selector;
bx_descriptor_t descriptor;
Bit32u dword1, dword2;
// NULL selector is OK, will leave cache invalid
if ( (raw_selector & 0xfffc) != 0 )
{
bx_bool good = fetch_raw_descriptor2(&selector, &dword1, &dword2);
if (!good) {
BX_ERROR(("task_switch(%s): bad selector fetch !", strseg(seg)));
exception(BX_TS_EXCEPTION, raw_selector & 0xfffc, 0);
}
parse_descriptor(dword1, dword2, &descriptor);
if (descriptor.valid==0 || descriptor.segment==0 ||
(descriptor.u.segment.executable &&
descriptor.u.segment.r_w==0))
{
BX_ERROR(("task_switch(%s): not a writeable data segment !", strseg(seg)));
exception(BX_TS_EXCEPTION, raw_selector & 0xfffc, 0);
}
if (descriptor.type < 12 &&
(descriptor.dpl < cs_rpl || descriptor.dpl < selector.rpl))
{
BX_ERROR(("task_switch(%s): descriptor DPL check failed !", strseg(seg)));
exception(BX_TS_EXCEPTION, raw_selector & 0xfffc, 0);
}
if (! IS_PRESENT(descriptor)) {
BX_ERROR(("task_switch(%s): descriptor not present !", strseg(seg)));
exception(BX_NP_EXCEPTION, raw_selector & 0xfffc, 0);
}
// All checks pass, fill in shadow cache
seg->cache = descriptor;
}
}
void BX_CPU_C::get_SS_ESP_from_TSS(unsigned pl, Bit16u *ss, Bit32u *esp)
{
if (BX_CPU_THIS_PTR tr.cache.valid==0)