Fix code duplication in tas
This commit is contained in:
parent
246d89d6a3
commit
086ee4c9aa
@ -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 ) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user