Begin differentiating 286 and 386 descriptors
This commit is contained in:
parent
210423d577
commit
545c290785
4 changed files with 124 additions and 100 deletions
|
|
@ -1821,6 +1821,21 @@ if (DEBUGGER) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Debugger.SYSDESCS = {
|
||||||
|
0x0100: ["tss286", false],
|
||||||
|
0x0200: ["ldt", false],
|
||||||
|
0x0300: ["busy tss286", false],
|
||||||
|
0x0400: ["call gate", true],
|
||||||
|
0x0500: ["task gate", true],
|
||||||
|
0x0600: ["int gate286", true],
|
||||||
|
0x0700: ["trap gate286", true],
|
||||||
|
0x0900: ["tss386", false],
|
||||||
|
0x0B00: ["busy tss386", false],
|
||||||
|
0x0C00: ["call gate386", true],
|
||||||
|
0x0E00: ["int gate386", true],
|
||||||
|
0x0F00: ["trap gate386", true]
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dumpDesc(s)
|
* dumpDesc(s)
|
||||||
*
|
*
|
||||||
|
|
@ -1862,34 +1877,10 @@ if (DEBUGGER) {
|
||||||
if (seg.type & X86.DESC.ACC.TYPE.ACCESSED) sType += ",accessed";
|
if (seg.type & X86.DESC.ACC.TYPE.ACCESSED) sType += ",accessed";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch(seg.type) {
|
var sysDesc = Debugger.SYSDESCS[seg.type];
|
||||||
case X86.DESC.ACC.TYPE.TSS:
|
if (sysDesc) {
|
||||||
sType = "tss";
|
sType = sysDesc[0];
|
||||||
break;
|
fGate = sysDesc[1];
|
||||||
case X86.DESC.ACC.TYPE.LDT:
|
|
||||||
sType = "ldt";
|
|
||||||
break;
|
|
||||||
case X86.DESC.ACC.TYPE.TSS_BUSY:
|
|
||||||
sType = "busy tss";
|
|
||||||
break;
|
|
||||||
case X86.DESC.ACC.TYPE.GATE_CALL:
|
|
||||||
sType = "call gate";
|
|
||||||
fGate = true;
|
|
||||||
break;
|
|
||||||
case X86.DESC.ACC.TYPE.GATE_TASK:
|
|
||||||
sType = "task gate";
|
|
||||||
fGate = true;
|
|
||||||
break;
|
|
||||||
case X86.DESC.ACC.TYPE.GATE_INT:
|
|
||||||
sType = "int gate";
|
|
||||||
fGate = true;
|
|
||||||
break;
|
|
||||||
case X86.DESC.ACC.TYPE.GATE_TRAP:
|
|
||||||
sType = "trap gate";
|
|
||||||
fGate = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,8 +91,8 @@ var X86 = {
|
||||||
MP: 0x0002, // monitor processor extension (ie, coprocessor)
|
MP: 0x0002, // monitor processor extension (ie, coprocessor)
|
||||||
EM: 0x0004, // emulate processor extension
|
EM: 0x0004, // emulate processor extension
|
||||||
TS: 0x0008, // task switch indicator
|
TS: 0x0008, // task switch indicator
|
||||||
ON: 0xfff0, // on the 80286, these bits are always on (TODO: Verify)
|
ON: 0xFFF0, // on the 80286, these bits are always on (TODO: Verify)
|
||||||
MASK: 0xffff // these are the only (MSW) bits that the 80286 can access (within CR0)
|
MASK: 0xFFFF // these are the only (MSW) bits that the 80286 can access (within CR0)
|
||||||
},
|
},
|
||||||
ET: 0x00000010, // coprocessor type (80287 or 80387); always 1 on post-80386 CPUs
|
ET: 0x00000010, // coprocessor type (80287 or 80387); always 1 on post-80386 CPUs
|
||||||
PG: 0x80000000|0 // 0: paging disabled
|
PG: 0x80000000|0 // 0: paging disabled
|
||||||
|
|
@ -100,7 +100,7 @@ var X86 = {
|
||||||
SEL: {
|
SEL: {
|
||||||
RPL: 0x0003, // requested privilege level (0-3)
|
RPL: 0x0003, // requested privilege level (0-3)
|
||||||
LDT: 0x0004, // table indicator (0: GDT, 1: LDT)
|
LDT: 0x0004, // table indicator (0: GDT, 1: LDT)
|
||||||
MASK: 0xfff8 // table index
|
MASK: 0xFFF8 // table index
|
||||||
},
|
},
|
||||||
DESC: { // Descriptor Table Entry
|
DESC: { // Descriptor Table Entry
|
||||||
LIMIT: { // LIMIT bits 0-15 (or OFFSET if this is an INTERRUPT or TRAP gate)
|
LIMIT: { // LIMIT bits 0-15 (or OFFSET if this is an INTERRUPT or TRAP gate)
|
||||||
|
|
@ -111,12 +111,12 @@ var X86 = {
|
||||||
},
|
},
|
||||||
ACC: { // bit definitions for the access word (offset 0x4)
|
ACC: { // bit definitions for the access word (offset 0x4)
|
||||||
OFFSET: 0x4,
|
OFFSET: 0x4,
|
||||||
BASE1623: 0x00ff, // (not used if this a TASK, INTERRUPT or TRAP gate; bits 0-5 are parm count for CALL gates)
|
BASE1623: 0x00FF, // (not used if this a TASK, INTERRUPT or TRAP gate; bits 0-5 are parm count for CALL gates)
|
||||||
TYPE: {
|
TYPE: {
|
||||||
OFFSET: 0x5,
|
OFFSET: 0x5,
|
||||||
MASK: 0x1f00,
|
MASK: 0x1F00,
|
||||||
SEG: 0x1000,
|
SEG: 0x1000,
|
||||||
NONSEG: 0x0f00,
|
NONSEG: 0x0F00,
|
||||||
/*
|
/*
|
||||||
* The following bits apply only when SEG is set
|
* The following bits apply only when SEG is set
|
||||||
*/
|
*/
|
||||||
|
|
@ -130,21 +130,26 @@ var X86 = {
|
||||||
* The following are all the possible (valid) types (well, except for the variations
|
* The following are all the possible (valid) types (well, except for the variations
|
||||||
* of DATA and CODE where the ACCESSED bit (0x0100) may also be set)
|
* of DATA and CODE where the ACCESSED bit (0x0100) may also be set)
|
||||||
*/
|
*/
|
||||||
TSS: 0x0100,
|
TSS286: 0x0100,
|
||||||
LDT: 0x0200,
|
LDT: 0x0200,
|
||||||
TSS_BUSY: 0x0300,
|
TSS286_BUSY: 0x0300,
|
||||||
GATE_CALL: 0x0400,
|
GATE_CALL: 0x0400,
|
||||||
GATE_TASK: 0x0500,
|
GATE_TASK: 0x0500,
|
||||||
GATE_INT: 0x0600,
|
GATE286_INT: 0x0600,
|
||||||
GATE_TRAP: 0x0700,
|
GATE286_TRAP: 0x0700,
|
||||||
|
TSS386: 0x0900, // 80386 and up
|
||||||
|
TSS386_BUSY: 0x0B00, // 80386 and up
|
||||||
|
GATE386_CALL: 0x0C00, // 80386 and up
|
||||||
|
GATE386_INT: 0x0E00, // 80386 and up
|
||||||
|
GATE386_TRAP: 0x0F00, // 80386 and up
|
||||||
DATA_READONLY: 0x1000,
|
DATA_READONLY: 0x1000,
|
||||||
DATA_WRITABLE: 0x1200,
|
DATA_WRITABLE: 0x1200,
|
||||||
DATA_EXPDOWN_READONLY: 0x1400,
|
DATA_EXPDOWN_READONLY: 0x1400,
|
||||||
DATA_EXPDOWN_WRITABLE: 0x1600,
|
DATA_EXPDOWN_WRITABLE: 0x1600,
|
||||||
CODE_EXECONLY: 0x1800,
|
CODE_EXECONLY: 0x1800,
|
||||||
CODE_READABLE: 0x1a00,
|
CODE_READABLE: 0x1A00,
|
||||||
CODE_CONFORMING: 0x1c00,
|
CODE_CONFORMING: 0x1C00,
|
||||||
CODE_CONFORMING_READABLE: 0x1e00
|
CODE_CONFORMING_READABLE: 0x1E00
|
||||||
},
|
},
|
||||||
DPL: {
|
DPL: {
|
||||||
MASK: 0x6000,
|
MASK: 0x6000,
|
||||||
|
|
@ -155,7 +160,7 @@ var X86 = {
|
||||||
},
|
},
|
||||||
EXT: { // descriptor extension word (reserved on the 80286; "must be zero")
|
EXT: { // descriptor extension word (reserved on the 80286; "must be zero")
|
||||||
OFFSET: 0x6,
|
OFFSET: 0x6,
|
||||||
LIMIT1619: 0x000f,
|
LIMIT1619: 0x000F,
|
||||||
AVAIL: 0x0010, // NOTE: set in various descriptors in OS/2
|
AVAIL: 0x0010, // NOTE: set in various descriptors in OS/2
|
||||||
/*
|
/*
|
||||||
* The BIG bit is known as the D bit for code segments; when set, all addresses and operands
|
* The BIG bit is known as the D bit for code segments; when set, all addresses and operands
|
||||||
|
|
@ -167,52 +172,80 @@ var X86 = {
|
||||||
*/
|
*/
|
||||||
BIG: 0x0040, // clear if default operand/address size is 16-bit, set if 32-bit
|
BIG: 0x0040, // clear if default operand/address size is 16-bit, set if 32-bit
|
||||||
LIMITPAGES: 0x0080, // clear if limit granularity is bytes, set if limit granularity is 4Kb pages
|
LIMITPAGES: 0x0080, // clear if limit granularity is bytes, set if limit granularity is 4Kb pages
|
||||||
BASE2431: 0xff00
|
BASE2431: 0xFF00
|
||||||
},
|
},
|
||||||
INVALID: 0 // use X86.DESC.INVALID for invalid DESC values
|
INVALID: 0 // use X86.DESC.INVALID for invalid DESC values
|
||||||
},
|
},
|
||||||
LADDR: { // linear address
|
LADDR: { // linear address
|
||||||
PDE: { // index of page directory entry
|
PDE: { // index of page directory entry
|
||||||
MASK: 0xffc00000|0,
|
MASK: 0xFFC00000|0,
|
||||||
SHIFT: 20 // (addr & DIR.MASK) >>> DIR.SHIFT yields a page directory offset (ie, index * 4)
|
SHIFT: 20 // (addr & DIR.MASK) >>> DIR.SHIFT yields a page directory offset (ie, index * 4)
|
||||||
},
|
},
|
||||||
PTE: { // index of page table entry
|
PTE: { // index of page table entry
|
||||||
MASK: 0x003ff000,
|
MASK: 0x003FF000,
|
||||||
SHIFT: 10 // (addr & PAGE.MASK) >>> PAGE.SHIFT yields a page table offset (ie, index * 4)
|
SHIFT: 10 // (addr & PAGE.MASK) >>> PAGE.SHIFT yields a page table offset (ie, index * 4)
|
||||||
},
|
},
|
||||||
OFFSET: 0x00000fff
|
OFFSET: 0x00000FFF
|
||||||
},
|
},
|
||||||
PTE: {
|
PTE: {
|
||||||
FRAME: 0xfffff000|0,
|
FRAME: 0xFFFFF000|0,
|
||||||
DIRTY: 0x00000040, // page has been modified
|
DIRTY: 0x00000040, // page has been modified
|
||||||
ACCESSED: 0x00000020, // page has been accessed
|
ACCESSED: 0x00000020, // page has been accessed
|
||||||
USER: 0x00000004, // set for user level (CPL 3), clear for supervisor level (CPL 0-2)
|
USER: 0x00000004, // set for user level (CPL 3), clear for supervisor level (CPL 0-2)
|
||||||
READWRITE: 0x00000002, // set for read/write, clear for read-only (affects CPL 3 only)
|
READWRITE: 0x00000002, // set for read/write, clear for read-only (affects CPL 3 only)
|
||||||
PRESENT: 0x00000001 // set for present page, clear for not-present page
|
PRESENT: 0x00000001 // set for present page, clear for not-present page
|
||||||
},
|
},
|
||||||
TSS: {
|
TSS286: {
|
||||||
PREV_TSS: 0x00,
|
PREV_TSS: 0x00,
|
||||||
CPL0_SP: 0x02, // start of values altered by task switches
|
CPL0_SP: 0x02, // start of values altered by task switches
|
||||||
CPL0_SS: 0x04,
|
CPL0_SS: 0x04,
|
||||||
CPL1_SP: 0x06,
|
CPL1_SP: 0x06,
|
||||||
CPL1_SS: 0x08,
|
CPL1_SS: 0x08,
|
||||||
CPL2_SP: 0x0a,
|
CPL2_SP: 0x0A,
|
||||||
CPL2_SS: 0x0c,
|
CPL2_SS: 0x0C,
|
||||||
TASK_IP: 0x0e,
|
TASK_IP: 0x0E,
|
||||||
TASK_PS: 0x10,
|
TASK_PS: 0x10,
|
||||||
TASK_AX: 0x12,
|
TASK_AX: 0x12,
|
||||||
TASK_CX: 0x14,
|
TASK_CX: 0x14,
|
||||||
TASK_DX: 0x16,
|
TASK_DX: 0x16,
|
||||||
TASK_BX: 0x18,
|
TASK_BX: 0x18,
|
||||||
TASK_SP: 0x1a,
|
TASK_SP: 0x1A,
|
||||||
TASK_BP: 0x1c,
|
TASK_BP: 0x1C,
|
||||||
TASK_SI: 0x1e,
|
TASK_SI: 0x1E,
|
||||||
TASK_DI: 0x20,
|
TASK_DI: 0x20,
|
||||||
TASK_ES: 0x22,
|
TASK_ES: 0x22,
|
||||||
TASK_CS: 0x24,
|
TASK_CS: 0x24,
|
||||||
TASK_SS: 0x26,
|
TASK_SS: 0x26,
|
||||||
TASK_DS: 0x28, // end of values altered by task switches
|
TASK_DS: 0x28, // end of values altered by task switches
|
||||||
TASK_LDT: 0x2a
|
TASK_LDT: 0x2A
|
||||||
|
},
|
||||||
|
TSS386: {
|
||||||
|
PREV_TSS: 0x00,
|
||||||
|
CPL0_ESP: 0x04, // start of values altered by task switches
|
||||||
|
CPL0_SS: 0x08,
|
||||||
|
CPL1_ESP: 0x0c,
|
||||||
|
CPL1_SS: 0x10,
|
||||||
|
CPL2_ESP: 0x14,
|
||||||
|
CPL2_SS: 0x18,
|
||||||
|
TASK_CR3: 0x1C, // (not in TSS286)
|
||||||
|
TASK_EIP: 0x20,
|
||||||
|
TASK_PS: 0x24,
|
||||||
|
TASK_EAX: 0x28,
|
||||||
|
TASK_ECX: 0x2C,
|
||||||
|
TASK_EDX: 0x30,
|
||||||
|
TASK_EBX: 0x34,
|
||||||
|
TASK_ESP: 0x38,
|
||||||
|
TASK_EBP: 0x3C,
|
||||||
|
TASK_ESI: 0x40,
|
||||||
|
TASK_EDI: 0x44,
|
||||||
|
TASK_ES: 0x48,
|
||||||
|
TASK_CS: 0x4C,
|
||||||
|
TASK_SS: 0x50,
|
||||||
|
TASK_DS: 0x54,
|
||||||
|
TASK_FS: 0x58, // (not in TSS286)
|
||||||
|
TASK_GS: 0x5C, // (not in TSS286) end of values altered by task switches
|
||||||
|
TASK_LDT: 0x60,
|
||||||
|
TASK_IOPM: 0x64 // (not in TSS286)
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
* Processor Exception Interrupts
|
* Processor Exception Interrupts
|
||||||
|
|
@ -260,7 +293,7 @@ var X86 = {
|
||||||
EXT: 0x0001,
|
EXT: 0x0001,
|
||||||
IDT: 0x0002,
|
IDT: 0x0002,
|
||||||
LDT: 0x0004,
|
LDT: 0x0004,
|
||||||
MASK: 0xfff8 // index of corresponding entry in GDT, LDT or IDT
|
MASK: 0xFFF8 // index of corresponding entry in GDT, LDT or IDT
|
||||||
},
|
},
|
||||||
RESULT: {
|
RESULT: {
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -1244,7 +1244,7 @@ X86.fnIRET = function IRET()
|
||||||
if (this.regCR0 & X86.CR0.MSW.PE) {
|
if (this.regCR0 & X86.CR0.MSW.PE) {
|
||||||
if (this.regPS & X86.PS.NT) {
|
if (this.regPS & X86.PS.NT) {
|
||||||
var addrNew = this.segTSS.base;
|
var addrNew = this.segTSS.base;
|
||||||
var sel = this.getShort(addrNew + X86.TSS.PREV_TSS);
|
var sel = this.getShort(addrNew + X86.TSS286.PREV_TSS);
|
||||||
this.segCS.switchTSS(sel, false);
|
this.segCS.switchTSS(sel, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1651,7 +1651,7 @@ X86.fnLTR = function LTR(dst, src)
|
||||||
this.opFlags |= X86.OPFLAG.NOWRITE;
|
this.opFlags |= X86.OPFLAG.NOWRITE;
|
||||||
if (this.segTSS.load(dst) !== X86.ADDR_INVALID) {
|
if (this.segTSS.load(dst) !== X86.ADDR_INVALID) {
|
||||||
this.setShort(this.segTSS.addrDesc + X86.DESC.ACC.OFFSET, this.segTSS.acc |= X86.DESC.ACC.TYPE.LDT);
|
this.setShort(this.segTSS.addrDesc + X86.DESC.ACC.OFFSET, this.segTSS.acc |= X86.DESC.ACC.TYPE.LDT);
|
||||||
this.segTSS.type = X86.DESC.ACC.TYPE.TSS_BUSY;
|
this.segTSS.type = X86.DESC.ACC.TYPE.TSS286_BUSY;
|
||||||
}
|
}
|
||||||
this.nStepCycles -= (17 + (this.regEA === X86.ADDR_INVALID? 0 : 2));
|
this.nStepCycles -= (17 + (this.regEA === X86.ADDR_INVALID? 0 : 2));
|
||||||
return dst;
|
return dst;
|
||||||
|
|
|
||||||
|
|
@ -554,7 +554,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
|
||||||
}
|
}
|
||||||
fGate = false;
|
fGate = false;
|
||||||
}
|
}
|
||||||
else if (type == X86.DESC.ACC.TYPE.TSS) {
|
else if (type == X86.DESC.ACC.TYPE.TSS286) {
|
||||||
if (!this.switchTSS(sel, fCall)) {
|
if (!this.switchTSS(sel, fCall)) {
|
||||||
base = addrDesc = X86.ADDR_INVALID;
|
base = addrDesc = X86.ADDR_INVALID;
|
||||||
break;
|
break;
|
||||||
|
|
@ -567,13 +567,13 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
|
||||||
nFaultError = sel;
|
nFaultError = sel;
|
||||||
if (rpl < this.cpl) rpl = this.cpl; // set RPL to max(RPL,CPL) for call gates
|
if (rpl < this.cpl) rpl = this.cpl; // set RPL to max(RPL,CPL) for call gates
|
||||||
}
|
}
|
||||||
else if (type == X86.DESC.ACC.TYPE.GATE_INT) {
|
else if (type == X86.DESC.ACC.TYPE.GATE286_INT) {
|
||||||
fGate = true;
|
fGate = true;
|
||||||
regPSMask = ~(X86.PS.NT | X86.PS.TF | X86.PS.IF);
|
regPSMask = ~(X86.PS.NT | X86.PS.TF | X86.PS.IF);
|
||||||
nFaultError = sel | X86.ERRCODE.EXT;
|
nFaultError = sel | X86.ERRCODE.EXT;
|
||||||
cpu.assert(!(acc & 0x1f));
|
cpu.assert(!(acc & 0x1f));
|
||||||
}
|
}
|
||||||
else if (type == X86.DESC.ACC.TYPE.GATE_TRAP) {
|
else if (type == X86.DESC.ACC.TYPE.GATE286_TRAP) {
|
||||||
fGate = true;
|
fGate = true;
|
||||||
regPSMask = ~(X86.PS.NT | X86.PS.TF);
|
regPSMask = ~(X86.PS.NT | X86.PS.TF);
|
||||||
nFaultError = sel | X86.ERRCODE.EXT;
|
nFaultError = sel | X86.ERRCODE.EXT;
|
||||||
|
|
@ -618,7 +618,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
|
||||||
regSP += 2;
|
regSP += 2;
|
||||||
}
|
}
|
||||||
addrTSS = cpu.segTSS.base;
|
addrTSS = cpu.segTSS.base;
|
||||||
offSP = (this.cpl << 2) + X86.TSS.CPL0_SP;
|
offSP = (this.cpl << 2) + X86.TSS286.CPL0_SP;
|
||||||
offSS = offSP + 2;
|
offSS = offSP + 2;
|
||||||
regSSPrev = cpu.getSS();
|
regSSPrev = cpu.getSS();
|
||||||
regSPPrev = cpu.getSP();
|
regSPPrev = cpu.getSP();
|
||||||
|
|
@ -692,7 +692,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (this.id == X86Seg.ID.TSS) {
|
else if (this.id == X86Seg.ID.TSS) {
|
||||||
if (!selMasked || type != X86.DESC.ACC.TYPE.TSS && type != X86.DESC.ACC.TYPE.TSS_BUSY) {
|
if (!selMasked || type != X86.DESC.ACC.TYPE.TSS286 && type != X86.DESC.ACC.TYPE.TSS286_BUSY) {
|
||||||
if (!fSuppress) X86.fnFault.call(cpu, X86.EXCEPTION.TS_FAULT, sel, true);
|
if (!fSuppress) X86.fnFault.call(cpu, X86.EXCEPTION.TS_FAULT, sel, true);
|
||||||
base = addrDesc = X86.ADDR_INVALID;
|
base = addrDesc = X86.ADDR_INVALID;
|
||||||
break;
|
break;
|
||||||
|
|
@ -702,7 +702,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
|
||||||
/*
|
/*
|
||||||
* For LSL, we must support any descriptor marked X86.DESC.ACC.TYPE.SEG, as well as TSS and LDT descriptors.
|
* For LSL, we must support any descriptor marked X86.DESC.ACC.TYPE.SEG, as well as TSS and LDT descriptors.
|
||||||
*/
|
*/
|
||||||
if (!(type & X86.DESC.ACC.TYPE.SEG) && type > X86.DESC.ACC.TYPE.TSS_BUSY) {
|
if (!(type & X86.DESC.ACC.TYPE.SEG) && type > X86.DESC.ACC.TYPE.TSS286_BUSY) {
|
||||||
base = addrDesc = X86.ADDR_INVALID;
|
base = addrDesc = X86.ADDR_INVALID;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -761,11 +761,11 @@ X86Seg.prototype.switchTSS = function switchTSS(selNew, fNest)
|
||||||
/*
|
/*
|
||||||
* TODO: Verify that it is (always) correct to require that the BUSY bit be currently set.
|
* TODO: Verify that it is (always) correct to require that the BUSY bit be currently set.
|
||||||
*/
|
*/
|
||||||
if (cpu.segTSS.type != X86.DESC.ACC.TYPE.TSS_BUSY) {
|
if (cpu.segTSS.type != X86.DESC.ACC.TYPE.TSS286_BUSY) {
|
||||||
X86.fnFault.call(cpu, X86.EXCEPTION.TS_FAULT, selNew, true);
|
X86.fnFault.call(cpu, X86.EXCEPTION.TS_FAULT, selNew, true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cpu.setShort(cpu.segTSS.addrDesc + X86.DESC.ACC.OFFSET, (cpu.segTSS.acc & ~X86.DESC.ACC.TYPE.TSS_BUSY) | X86.DESC.ACC.TYPE.TSS);
|
cpu.setShort(cpu.segTSS.addrDesc + X86.DESC.ACC.OFFSET, (cpu.segTSS.acc & ~X86.DESC.ACC.TYPE.TSS286_BUSY) | X86.DESC.ACC.TYPE.TSS286);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu.segTSS.load(selNew) === X86.ADDR_INVALID) {
|
if (cpu.segTSS.load(selNew) === X86.ADDR_INVALID) {
|
||||||
|
|
@ -777,66 +777,66 @@ X86Seg.prototype.switchTSS = function switchTSS(selNew, fNest)
|
||||||
this.dbg.message((fNest? "Task switch" : "Task return") + ": TR " + str.toHexWord(selOld) + " (%" + str.toHex(addrOld, 6) + "), new TR " + str.toHexWord(selNew) + " (%" + str.toHex(addrNew, 6) + ")");
|
this.dbg.message((fNest? "Task switch" : "Task return") + ": TR " + str.toHexWord(selOld) + " (%" + str.toHex(addrOld, 6) + "), new TR " + str.toHexWord(selNew) + " (%" + str.toHex(addrNew, 6) + ")");
|
||||||
}
|
}
|
||||||
if (fNest === false) {
|
if (fNest === false) {
|
||||||
if (cpu.segTSS.type != X86.DESC.ACC.TYPE.TSS_BUSY) {
|
if (cpu.segTSS.type != X86.DESC.ACC.TYPE.TSS286_BUSY) {
|
||||||
X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, selNew, true);
|
X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, selNew, true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (cpu.segTSS.type == X86.DESC.ACC.TYPE.TSS_BUSY) {
|
if (cpu.segTSS.type == X86.DESC.ACC.TYPE.TSS286_BUSY) {
|
||||||
X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, selNew, true);
|
X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, selNew, true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cpu.setShort(cpu.segTSS.addrDesc + X86.DESC.ACC.OFFSET, cpu.segTSS.acc |= X86.DESC.ACC.TYPE.TSS_BUSY);
|
cpu.setShort(cpu.segTSS.addrDesc + X86.DESC.ACC.OFFSET, cpu.segTSS.acc |= X86.DESC.ACC.TYPE.TSS286_BUSY);
|
||||||
cpu.segTSS.type = X86.DESC.ACC.TYPE.TSS_BUSY;
|
cpu.segTSS.type = X86.DESC.ACC.TYPE.TSS286_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update the old TSS
|
* Update the old TSS
|
||||||
*/
|
*/
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_IP, cpu.getIP());
|
cpu.setShort(addrOld + X86.TSS286.TASK_IP, cpu.getIP());
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_PS, cpu.getPS());
|
cpu.setShort(addrOld + X86.TSS286.TASK_PS, cpu.getPS());
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_AX, cpu.regEAX);
|
cpu.setShort(addrOld + X86.TSS286.TASK_AX, cpu.regEAX);
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_CX, cpu.regECX);
|
cpu.setShort(addrOld + X86.TSS286.TASK_CX, cpu.regECX);
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_DX, cpu.regEDX);
|
cpu.setShort(addrOld + X86.TSS286.TASK_DX, cpu.regEDX);
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_BX, cpu.regEBX);
|
cpu.setShort(addrOld + X86.TSS286.TASK_BX, cpu.regEBX);
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_SP, cpu.getSP());
|
cpu.setShort(addrOld + X86.TSS286.TASK_SP, cpu.getSP());
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_BP, cpu.regEBP);
|
cpu.setShort(addrOld + X86.TSS286.TASK_BP, cpu.regEBP);
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_SI, cpu.regESI);
|
cpu.setShort(addrOld + X86.TSS286.TASK_SI, cpu.regESI);
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_DI, cpu.regEDI);
|
cpu.setShort(addrOld + X86.TSS286.TASK_DI, cpu.regEDI);
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_ES, cpu.segES.sel);
|
cpu.setShort(addrOld + X86.TSS286.TASK_ES, cpu.segES.sel);
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_CS, cpu.segCS.sel);
|
cpu.setShort(addrOld + X86.TSS286.TASK_CS, cpu.segCS.sel);
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_SS, cpu.segSS.sel);
|
cpu.setShort(addrOld + X86.TSS286.TASK_SS, cpu.segSS.sel);
|
||||||
cpu.setShort(addrOld + X86.TSS.TASK_DS, cpu.segDS.sel);
|
cpu.setShort(addrOld + X86.TSS286.TASK_DS, cpu.segDS.sel);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reload all registers from the new TSS; it's important to reload the LDTR sooner
|
* Reload all registers from the new TSS; it's important to reload the LDTR sooner
|
||||||
* rather than later, so that as segment registers are reloaded, any LDT selectors will
|
* rather than later, so that as segment registers are reloaded, any LDT selectors will
|
||||||
* will be located in the correct table.
|
* will be located in the correct table.
|
||||||
*/
|
*/
|
||||||
cpu.segLDT.load(cpu.getShort(addrNew + X86.TSS.TASK_LDT));
|
cpu.segLDT.load(cpu.getShort(addrNew + X86.TSS286.TASK_LDT));
|
||||||
cpu.setPS(cpu.getShort(addrNew + X86.TSS.TASK_PS) | (fNest? X86.PS.NT : 0));
|
cpu.setPS(cpu.getShort(addrNew + X86.TSS286.TASK_PS) | (fNest? X86.PS.NT : 0));
|
||||||
cpu.assert(!fNest || !!(cpu.regPS & X86.PS.NT));
|
cpu.assert(!fNest || !!(cpu.regPS & X86.PS.NT));
|
||||||
cpu.regEAX = cpu.getShort(addrNew + X86.TSS.TASK_AX);
|
cpu.regEAX = cpu.getShort(addrNew + X86.TSS286.TASK_AX);
|
||||||
cpu.regECX = cpu.getShort(addrNew + X86.TSS.TASK_CX);
|
cpu.regECX = cpu.getShort(addrNew + X86.TSS286.TASK_CX);
|
||||||
cpu.regEDX = cpu.getShort(addrNew + X86.TSS.TASK_DX);
|
cpu.regEDX = cpu.getShort(addrNew + X86.TSS286.TASK_DX);
|
||||||
cpu.regEBX = cpu.getShort(addrNew + X86.TSS.TASK_BX);
|
cpu.regEBX = cpu.getShort(addrNew + X86.TSS286.TASK_BX);
|
||||||
cpu.regEBP = cpu.getShort(addrNew + X86.TSS.TASK_BP);
|
cpu.regEBP = cpu.getShort(addrNew + X86.TSS286.TASK_BP);
|
||||||
cpu.regESI = cpu.getShort(addrNew + X86.TSS.TASK_SI);
|
cpu.regESI = cpu.getShort(addrNew + X86.TSS286.TASK_SI);
|
||||||
cpu.regEDI = cpu.getShort(addrNew + X86.TSS.TASK_DI);
|
cpu.regEDI = cpu.getShort(addrNew + X86.TSS286.TASK_DI);
|
||||||
cpu.segES.load(cpu.getShort(addrNew + X86.TSS.TASK_ES));
|
cpu.segES.load(cpu.getShort(addrNew + X86.TSS286.TASK_ES));
|
||||||
cpu.segDS.load(cpu.getShort(addrNew + X86.TSS.TASK_DS));
|
cpu.segDS.load(cpu.getShort(addrNew + X86.TSS286.TASK_DS));
|
||||||
cpu.setCSIP(cpu.getShort(addrNew + X86.TSS.TASK_IP), cpu.getShort(addrNew + X86.TSS.TASK_CS));
|
cpu.setCSIP(cpu.getShort(addrNew + X86.TSS286.TASK_IP), cpu.getShort(addrNew + X86.TSS286.TASK_CS));
|
||||||
|
|
||||||
var offSS = X86.TSS.TASK_SS;
|
var offSS = X86.TSS286.TASK_SS;
|
||||||
var offSP = X86.TSS.TASK_SP;
|
var offSP = X86.TSS286.TASK_SP;
|
||||||
if (this.cpl < cplOld) {
|
if (this.cpl < cplOld) {
|
||||||
offSP = (this.cpl << 2) + X86.TSS.CPL0_SP;
|
offSP = (this.cpl << 2) + X86.TSS286.CPL0_SP;
|
||||||
offSS = offSP + 2;
|
offSS = offSP + 2;
|
||||||
}
|
}
|
||||||
cpu.setSS(cpu.getShort(addrNew + offSS), true);
|
cpu.setSS(cpu.getShort(addrNew + offSS), true);
|
||||||
cpu.setSP(cpu.getShort(addrNew + offSP));
|
cpu.setSP(cpu.getShort(addrNew + offSP));
|
||||||
|
|
||||||
if (fNest) cpu.setShort(addrNew + X86.TSS.PREV_TSS, selOld);
|
if (fNest) cpu.setShort(addrNew + X86.TSS286.PREV_TSS, selOld);
|
||||||
|
|
||||||
cpu.regCR0 |= X86.CR0.MSW.TS;
|
cpu.regCR0 |= X86.CR0.MSW.TS;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue