From a3f1df0ba7be42af09259fec809bd67d113a276b Mon Sep 17 00:00:00 2001 From: Jeff Parsons Date: Sun, 16 Aug 2015 08:41:13 -0700 Subject: [PATCH] Removed fSuppress hack from general-purpose segment register operations --- modules/pcjs/lib/debugger.js | 46 +++++--- modules/pcjs/lib/x86cpu.js | 6 +- modules/pcjs/lib/x86func.js | 8 +- modules/pcjs/lib/x86seg.js | 223 ++++++++++++++++++++--------------- 4 files changed, 166 insertions(+), 117 deletions(-) diff --git a/modules/pcjs/lib/debugger.js b/modules/pcjs/lib/debugger.js index e5ea2f122..a6b6914f7 100644 --- a/modules/pcjs/lib/debugger.js +++ b/modules/pcjs/lib/debugger.js @@ -1358,7 +1358,7 @@ if (DEBUGGER) { /* * Allocate a special segment "register" for our own use, whenever a requested selector is not currently loaded */ - this.segDebugger = new X86Seg(this.cpu, X86Seg.ID.DEBUG, "DBG"); + this.segDebugger = new X86Seg(this.cpu, X86Seg.ID.DBG, "DBG"); this.aaOpDescs = Debugger.aaOpDescs; if (this.cpu.model >= X86.MODEL_80186) { @@ -1531,21 +1531,16 @@ if (DEBUGGER) { if (sel === this.cpu.getGS()) return this.cpu.segGS; } /* - * Even if nSuppressBreaks is set, we'll allow the call if we're in real-mode, because - * a loadReal() request using segDebugger should generally be safe. + * Even if nSuppressBreaks is set, we'll allow the call in real-mode, + * because a loadReal() request using segDebugger should generally be safe. */ if (this.nSuppressBreaks && fProt || !this.segDebugger) return null; } - /* - * Note the load() function's fSuppress parameter, which the Debugger should ALWAYS set to true - * to avoid triggering a fault. Unfortunately, when paging is enabled, there's still the risk of - * triggering a page fault that will alter the machine's state, so be careful. - */ if (!fProt) { - this.segDebugger.loadReal(sel, true); + this.segDebugger.loadReal(sel); } else { - this.segDebugger.loadProt(sel, true); + this.segDebugger.loadProt(sel); } return this.segDebugger; }; @@ -1574,9 +1569,9 @@ if (DEBUGGER) { var seg = this.getSegment(dbgAddr.sel, dbgAddr.fProt); if (seg) { if (!fWrite) { - addr = seg.checkRead(dbgAddr.off, nb || 1, true); + addr = seg.checkReadDebugger(dbgAddr.off || 0, nb || 1); } else { - addr = seg.checkWrite(dbgAddr.off, nb || 1, true); + addr = seg.checkWriteDebugger(dbgAddr.off || 0, nb || 1); } dbgAddr.addr = addr; } @@ -3265,7 +3260,8 @@ if (DEBUGGER) { Debugger.prototype.addBreakpoint = function(aBreak, dbgAddr, fTempBreak) { var fSuccess = false; - this.nSuppressBreaks++; + + // this.nSuppressBreaks++; /* * We need to allow a temporary breakpoint at an address where they may already be a breakpoint. @@ -3277,6 +3273,7 @@ if (DEBUGGER) { if (aBreak != this.aBreakExec) { var addr = this.getAddr(dbgAddr); if (addr == X86.ADDR_INVALID) { + this.println("invalid address: " + this.hexAddr(dbgAddr)); fSuccess = false; } else { this.bus.addMemBreak(addr, aBreak == this.aBreakWrite); @@ -3306,7 +3303,8 @@ if (DEBUGGER) { } } - this.nSuppressBreaks--; + // this.nSuppressBreaks--; + return fSuccess; }; @@ -3454,6 +3452,7 @@ if (DEBUGGER) { * or history data (see checkInstruction), since we might not actually execute the current instruction. */ var fBreak = false; + if (!this.nSuppressBreaks++) { addr = this.mapBreakpoint(addr); @@ -3545,7 +3544,9 @@ if (DEBUGGER) { } } } + this.nSuppressBreaks--; + return fBreak; }; @@ -5791,6 +5792,11 @@ if (DEBUGGER) { case "DI": this.cpu.regEDI = (this.cpu.regEDI & ~0xffff) | (w & 0xffff); break; + /* + * DANGER: For any of the segment loads below, by going through the normal CPU + * segment load procedure, you run the risk of generating a fault in the machine + * if you're not careful. So, um, be careful. + */ case "DS": this.cpu.setDS(w); break; @@ -5852,7 +5858,12 @@ if (DEBUGGER) { this.cpu.setMSW(w); break; case "TR": - if (this.cpu.segTSS.load(w, true) === X86.ADDR_INVALID) { + /* + * DANGER: Like any of the segment loads above, by going through the normal CPU + * segment load procedure, you run the risk of generating a fault in the machine + * if you're not careful. So, um, be careful. + */ + if (this.cpu.segTSS.load(w) === X86.ADDR_INVALID) { fValid = false; } break; @@ -5889,6 +5900,11 @@ if (DEBUGGER) { case "EDI": this.cpu.regEDI = w; break; + /* + * DANGER: For any of the segment loads below, by going through the normal CPU + * segment load procedure, you run the risk of generating a fault in the machine + * if you're not careful. So, um, be careful. + */ case "FS": this.cpu.setFS(w); break; diff --git a/modules/pcjs/lib/x86cpu.js b/modules/pcjs/lib/x86cpu.js index 7013e3198..d8bbd47ea 100644 --- a/modules/pcjs/lib/x86cpu.js +++ b/modules/pcjs/lib/x86cpu.js @@ -1400,9 +1400,9 @@ X86CPU.prototype.resetRegs = function() * TODO: Verify what the 80286 actually sets addrGDT and addrGDTLimit to on reset (or if it leaves them alone). */ this.addrGDT = 0; this.addrGDTLimit = 0xffff; // GDTR - this.segLDT = new X86Seg(this, X86Seg.ID.LDT, "LDT", true); // LDTR - this.segTSS = new X86Seg(this, X86Seg.ID.TSS, "TSS", true); // TR - this.segVER = new X86Seg(this, X86Seg.ID.OTHER, "VER", true); // a scratch segment register for VERR and VERW instructions + this.segLDT = new X86Seg(this, X86Seg.ID.LDT, "LDT", true); // LDTR + this.segTSS = new X86Seg(this, X86Seg.ID.TSS, "TSS", true); // TR + this.segVER = new X86Seg(this, X86Seg.ID.VER, "VER", true); // a scratch segment register for VERR and VERW instructions this.setCSIP(0xfff0, 0xf000); // on an 80286 or 80386, the default CS:IP is 0xF000:0xFFF0 instead of 0xFFFF:0x0000 this.setCSBase(0xffff0000|0); // on an 80286 or 80386, all CS base address bits above bit 15 must be set } diff --git a/modules/pcjs/lib/x86func.js b/modules/pcjs/lib/x86func.js index fe5100e2d..b8e92d3b6 100644 --- a/modules/pcjs/lib/x86func.js +++ b/modules/pcjs/lib/x86func.js @@ -1396,7 +1396,7 @@ X86.fnLAR = function LAR(dst, src) * if we need a special check for them. */ this.clearZF(); - if (this.segVER.load(src, true) !== X86.ADDR_INVALID) { + if (this.segVER.load(src) !== X86.ADDR_INVALID) { if (this.segVER.dpl >= this.nCPL && this.segVER.dpl >= (src & X86.SEL.RPL)) { this.setZF(); dst = this.segVER.acc & ~X86.DESC.ACC.BASE1623; @@ -1700,7 +1700,7 @@ X86.fnLSL = function LSL(dst, src) * TODO: LSL is explicitly documented as ALSO requiring a non-null selector, so we check X86.SEL.MASK; * are there any other instructions that were, um, less explicit but also require a non-null selector? */ - if ((src & X86.SEL.MASK) && this.segVER.load(src, true) !== X86.ADDR_INVALID) { + if ((src & X86.SEL.MASK) && this.segVER.load(src) !== X86.ADDR_INVALID) { var fConforming = ((this.segVER.acc & X86.DESC.ACC.TYPE.CODE_CONFORMING) == X86.DESC.ACC.TYPE.CODE_CONFORMING); if ((fConforming || this.segVER.dpl >= this.nCPL) && this.segVER.dpl >= (src & X86.SEL.RPL)) { this.setZF(); @@ -3346,7 +3346,7 @@ X86.fnVERR = function VERR(dst, src) * descriptor table or the descriptor is not for a segment. */ this.nStepCycles -= (14 + (this.regEA === X86.ADDR_INVALID? 0 : 2)); - if (this.segVER.load(dst, true) !== X86.ADDR_INVALID) { + if (this.segVER.load(dst) !== X86.ADDR_INVALID) { /* * Verify that this is a readable segment; that is, of these four combinations (code+readable, * code+nonreadable, data+writable, date+nonwritable), make sure we're not the second combination. @@ -3388,7 +3388,7 @@ X86.fnVERW = function VERW(dst, src) * descriptor table or the descriptor is not for a segment. */ this.nStepCycles -= (14 + (this.regEA === X86.ADDR_INVALID? 0 : 2)); - if (this.segVER.load(dst, true) !== X86.ADDR_INVALID) { + if (this.segVER.load(dst) !== X86.ADDR_INVALID) { /* * Verify that this is a writable data segment */ diff --git a/modules/pcjs/lib/x86seg.js b/modules/pcjs/lib/x86seg.js index 2f45020d1..c7fea6fb5 100644 --- a/modules/pcjs/lib/x86seg.js +++ b/modules/pcjs/lib/x86seg.js @@ -131,21 +131,20 @@ X86Seg.ID = { STACK: 3, // "SS" TSS: 4, // "TSS" LDT: 5, // "LDT" - OTHER: 6, // "VER" - DEBUG: 7 // "DBG" + VER: 6, // "VER" + DBG: 7 // "DBG" }; /** - * loadReal(sel, fSuppress) + * loadReal(sel) * * The default segment load() function for real-mode. * * @this {X86Seg} * @param {number} sel - * @param {boolean} [fSuppress] is true to suppress any errors * @return {number} base address of selected segment, or ADDR_INVALID if error (TODO: No error conditions yet) */ -X86Seg.prototype.loadReal = function loadReal(sel, fSuppress) +X86Seg.prototype.loadReal = function loadReal(sel) { this.sel = sel & 0xffff; /* @@ -159,7 +158,7 @@ X86Seg.prototype.loadReal = function loadReal(sel, fSuppress) }; /** - * loadProt(sel, fSuppress) + * loadProt(sel) * * This replaces the segment's default load() function whenever the segment is notified via updateMode() by the * CPU's setProtMode() that the processor is now in protected-mode. @@ -178,10 +177,9 @@ X86Seg.prototype.loadReal = function loadReal(sel, fSuppress) * * @this {X86Seg} * @param {number} sel - * @param {boolean} [fSuppress] is true to suppress any errors, cycle assessment, etc * @return {number} base address of selected segment, or ADDR_INVALID if error */ -X86Seg.prototype.loadProt = function loadProt(sel, fSuppress) +X86Seg.prototype.loadProt = function loadProt(sel) { var addrDT; var addrDTLimit; @@ -204,11 +202,10 @@ X86Seg.prototype.loadProt = function loadProt(sel, fSuppress) * The ROM BIOS POST executes some test code in protected-mode without properly initializing the LDT, * which has no bearing on the ROM's own code, because it never loads any LDT selectors, but if at the same * time our Debugger attempts to validate a selector in one of its breakpoints, that could cause some - * grief here. We avoid that grief by 1) relying on the Debugger setting fSuppress to true, and 2) skipping - * segment lookup if the descriptor table being referenced is zero. Both tests are required, because - * there's nothing in the design of the CPU that prevents the GDT or LDT being at linear address zero. + * grief here. We avoid that grief by skipping segment lookup if the descriptor table being referenced is zero + * AND the Debugger's ID.DBG segment register is being used. */ - if (!fSuppress || addrDT) { + if (addrDT || this.id != X86Seg.ID.DBG) { var addrDesc = (addrDT + (sel & X86.SEL.MASK))|0; if ((addrDTLimit - addrDesc)|0 >= 7) { /* @@ -217,10 +214,10 @@ X86Seg.prototype.loadProt = function loadProt(sel, fSuppress) * starting with a 15-cycle difference. Obviously the difference will vary with the instruction, * and will be much greater whenever the load fails. */ - if (!fSuppress) cpu.nStepCycles -= 15; - return this.loadDesc8(addrDesc, sel, fSuppress); + if (this.id != X86Seg.ID.DBG) cpu.nStepCycles -= 15; + return this.loadDesc8(addrDesc, sel); } - if (!fSuppress) { + if (this.id < X86Seg.ID.VER) { X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel); } } @@ -278,7 +275,7 @@ X86Seg.prototype.loadIDTProt = function loadIDTProt(nIDT) }; /** - * checkReadReal(off, cb, fSuppress) + * checkReadReal(off, cb) * * TODO: Invoke X86.fnFault.call(this.cpu, X86.EXCEPTION.GP_FAULT) if off+cb is beyond offMax on 80186 and up; * also, determine whether fnFault() call should include an error code, since this is happening in real-mode. @@ -286,16 +283,15 @@ X86Seg.prototype.loadIDTProt = function loadIDTProt(nIDT) * @this {X86Seg} * @param {number} off is a segment-relative offset * @param {number} cb is number of bytes to check (1, 2 or 4) - * @param {boolean} [fSuppress] is true to suppress any errors * @return {number} corresponding linear address if valid, or ADDR_INVALID if error (TODO: No error conditions yet) */ -X86Seg.prototype.checkReadReal = function checkReadReal(off, cb, fSuppress) +X86Seg.prototype.checkReadReal = function checkReadReal(off, cb) { return (this.base + off)|0; }; /** - * checkWriteReal(off, cb, fSuppress) + * checkWriteReal(off, cb) * * TODO: Invoke X86.fnFault.call(this.cpu, X86.EXCEPTION.GP_FAULT) if off+cb is beyond offMax on 80186 and up; * also, determine whether fnFault() call should include an error code, since this is happening in real-mode. @@ -303,24 +299,22 @@ X86Seg.prototype.checkReadReal = function checkReadReal(off, cb, fSuppress) * @this {X86Seg} * @param {number} off is a segment-relative offset * @param {number} cb is number of bytes to check (1, 2 or 4) - * @param {boolean} [fSuppress] is true to suppress any errors * @return {number} corresponding linear address if valid, or ADDR_INVALID if error (TODO: No error conditions yet) */ -X86Seg.prototype.checkWriteReal = function checkWriteReal(off, cb, fSuppress) +X86Seg.prototype.checkWriteReal = function checkWriteReal(off, cb) { return (this.base + off)|0; }; /** - * checkReadProt(off, cb, fSuppress) + * checkReadProt(off, cb) * * @this {X86Seg} * @param {number} off is a segment-relative offset * @param {number} cb is number of bytes to check (1, 2 or 4) - * @param {boolean} [fSuppress] is true to suppress any errors * @return {number} corresponding linear address if valid, or ADDR_INVALID if not */ -X86Seg.prototype.checkReadProt = function checkReadProt(off, cb, fSuppress) +X86Seg.prototype.checkReadProt = function checkReadProt(off, cb) { /* * Since off could be a 32-bit value with the sign bit (bit 31) set, we must convert @@ -329,19 +323,18 @@ X86Seg.prototype.checkReadProt = function checkReadProt(off, cb, fSuppress) if ((off >>> 0) + cb <= this.offMax) { return (this.base + off)|0; } - return this.checkReadProtDisallowed(off, cb, fSuppress); + return this.checkReadProtDisallowed(off, cb); }; /** - * checkReadProtDown(off, cb, fSuppress) + * checkReadProtDown(off, cb) * * @this {X86Seg} * @param {number} off is a segment-relative offset * @param {number} cb is number of bytes to check (1, 2 or 4) - * @param {boolean} [fSuppress] is true to suppress any errors * @return {number} corresponding linear address if valid, ADDR_INVALID if not */ -X86Seg.prototype.checkReadProtDown = function checkReadProtDown(off, cb, fSuppress) +X86Seg.prototype.checkReadProtDown = function checkReadProtDown(off, cb) { /* * Since off could be a 32-bit value with the sign bit (bit 31) set, we must convert @@ -350,81 +343,117 @@ X86Seg.prototype.checkReadProtDown = function checkReadProtDown(off, cb, fSuppre if ((off >>> 0) + cb > this.offMax) { return (this.base + off)|0; } - return this.checkReadProtDisallowed(off, cb, fSuppress); + return this.checkReadProtDisallowed(off, cb); }; /** - * checkReadProtDisallowed(off, cb, fSuppress) + * checkReadProtDisallowed(off, cb) * * @this {X86Seg} * @param {number} off is a segment-relative offset * @param {number} cb is number of bytes to check (1, 2 or 4) - * @param {boolean} [fSuppress] is true to suppress any errors * @return {number} corresponding linear address if valid, ADDR_INVALID if not */ -X86Seg.prototype.checkReadProtDisallowed = function checkReadProtDisallowed(off, cb, fSuppress) +X86Seg.prototype.checkReadProtDisallowed = function checkReadProtDisallowed(off, cb) { - if (!fSuppress) { - X86.fnFault.call(this.cpu, X86.EXCEPTION.GP_FAULT, 0); + X86.fnFault.call(this.cpu, X86.EXCEPTION.GP_FAULT, 0); + return X86.ADDR_INVALID; +}; + +/** + * checkWriteProt(off, cb) + * + * @this {X86Seg} + * @param {number} off is a segment-relative offset + * @param {number} cb is number of bytes to check (1, 2 or 4) + * @return {number} corresponding linear address if valid, ADDR_INVALID if not + */ +X86Seg.prototype.checkWriteProt = function checkWriteProt(off, cb) +{ + /* + * Since off could be a 32-bit value with the sign bit (bit 31) set, we must convert + * it to an unsigned value using ">>>"; offMax was already converted at segment load time. + */ + if ((off >>> 0) + cb <= this.offMax) { + return (this.base + off)|0; + } + return this.checkWriteProtDisallowed(off, cb); +}; + +/** + * checkWriteProtDown(off, cb) + * + * @this {X86Seg} + * @param {number} off is a segment-relative offset + * @param {number} cb is number of bytes to check (1, 2 or 4) + * @return {number} corresponding linear address if valid, ADDR_INVALID if not + */ +X86Seg.prototype.checkWriteProtDown = function checkWriteProtDown(off, cb) +{ + /* + * Since off could be a 32-bit value with the sign bit (bit 31) set, we must convert + * it to an unsigned value using ">>>"; offMax was already converted at segment load time. + */ + if ((off >>> 0) + cb > this.offMax) { + return (this.base + off)|0; + } + return this.checkWriteProtDisallowed(off, cb); +}; + +/** + * checkWriteProtDisallowed(off, cb) + * + * @this {X86Seg} + * @param {number} off is a segment-relative offset + * @param {number} cb is number of bytes to check (1, 2 or 4) + * @return {number} corresponding linear address if valid, ADDR_INVALID if not + */ +X86Seg.prototype.checkWriteProtDisallowed = function checkWriteProtDisallowed(off, cb) +{ + X86.fnFault.call(this.cpu, X86.EXCEPTION.GP_FAULT, 0); + return X86.ADDR_INVALID; +}; + +/** + * checkReadDebugger(off, cb) + * + * @this {X86Seg} + * @param {number} off is a segment-relative offset + * @param {number} cb is number of bytes to check (1, 2 or 4) + * @return {number} corresponding linear address if valid, or ADDR_INVALID if error + */ +X86Seg.prototype.checkReadDebugger = function checkReadDebugger(off, cb) +{ + /* + * The Debugger doesn't have separate "check" interfaces for real and protected mode, + * since it's not performance-critical. If addrDesc is invalid, then we assume real mode. + */ + if (DEBUGGER) { + if (this.addrDesc === X86.ADDR_INVALID || (off >>> 0) + cb <= this.offMax) { + return (this.base + off)|0; + } } return X86.ADDR_INVALID; }; /** - * checkWriteProt(off, cb, fSuppress) + * checkWriteDebugger(off, cb) * * @this {X86Seg} * @param {number} off is a segment-relative offset * @param {number} cb is number of bytes to check (1, 2 or 4) - * @param {boolean} [fSuppress] is true to suppress any errors - * @return {number} corresponding linear address if valid, ADDR_INVALID if not + * @return {number} corresponding linear address if valid, or ADDR_INVALID if error */ -X86Seg.prototype.checkWriteProt = function checkWriteProt(off, cb, fSuppress) +X86Seg.prototype.checkWriteDebugger = function checkWriteDebugger(off, cb) { /* - * Since off could be a 32-bit value with the sign bit (bit 31) set, we must convert - * it to an unsigned value using ">>>"; offMax was already converted at segment load time. + * The Debugger doesn't have separate "check" interfaces for real and protected mode, + * since it's not performance-critical. If addrDesc is invalid, then we assume real mode. */ - if ((off >>> 0) + cb <= this.offMax) { - return (this.base + off)|0; - } - return this.checkWriteProtDisallowed(off, cb, fSuppress); -}; - -/** - * checkWriteProtDown(off, cb, fSuppress) - * - * @this {X86Seg} - * @param {number} off is a segment-relative offset - * @param {number} cb is number of bytes to check (1, 2 or 4) - * @param {boolean} [fSuppress] is true to suppress any errors - * @return {number} corresponding linear address if valid, ADDR_INVALID if not - */ -X86Seg.prototype.checkWriteProtDown = function checkWriteProtDown(off, cb, fSuppress) -{ - /* - * Since off could be a 32-bit value with the sign bit (bit 31) set, we must convert - * it to an unsigned value using ">>>"; offMax was already converted at segment load time. - */ - if ((off >>> 0) + cb > this.offMax) { - return (this.base + off)|0; - } - return this.checkWriteProtDisallowed(off, cb, fSuppress); -}; - -/** - * checkWriteProtDisallowed(off, cb, fSuppress) - * - * @this {X86Seg} - * @param {number} off is a segment-relative offset - * @param {number} cb is number of bytes to check (1, 2 or 4) - * @param {boolean} [fSuppress] is true to suppress any errors - * @return {number} corresponding linear address if valid, ADDR_INVALID if not - */ -X86Seg.prototype.checkWriteProtDisallowed = function checkWriteProtDisallowed(off, cb, fSuppress) -{ - if (!fSuppress) { - X86.fnFault.call(this.cpu, X86.EXCEPTION.GP_FAULT, 0); + if (DEBUGGER) { + if (this.addrDesc === X86.ADDR_INVALID || (off >>> 0) + cb <= this.offMax) { + return (this.base + off)|0; + } } return X86.ADDR_INVALID; }; @@ -491,13 +520,13 @@ X86Seg.prototype.loadDesc6 = function(addrDesc, sel) this.addrDesc = addrDesc; this.updateMode(true); - this.messageSeg(sel, base, limit, this.type); + if (DEBUG) this.messageSeg(sel, base, limit, this.type); return base; }; /** - * loadDesc8(addrDesc, sel, fSuppress) + * loadDesc8(addrDesc, sel) * * Used to load a protected-mode selector that refers to an 8-byte "descriptor table" (GDT, LDT, IDT) entry: * @@ -511,10 +540,9 @@ X86Seg.prototype.loadDesc6 = function(addrDesc, sel) * @this {X86Seg} * @param {number} addrDesc is the descriptor address * @param {number} sel is the associated selector, or nIDT*8 if IDT descriptor - * @param {boolean} [fSuppress] is true to suppress any errors, cycle assessment, etc * @return {number} base address of selected segment, or ADDR_INVALID if error */ -X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress) +X86Seg.prototype.loadDesc8 = function(addrDesc, sel) { var cpu = this.cpu; var limit = cpu.getShort(addrDesc + X86.DESC.LIMIT.OFFSET); @@ -547,7 +575,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress) var dpl = (acc & X86.DESC.ACC.DPL.MASK) >> X86.DESC.ACC.DPL.SHIFT; if (selMasked && !(acc & X86.DESC.ACC.PRESENT)) { - if (!fSuppress) X86.fnFault.call(cpu, X86.EXCEPTION.NP_FAULT, sel); + if (this.id < X86Seg.ID.VER) X86.fnFault.call(cpu, X86.EXCEPTION.NP_FAULT, sel); base = addrDesc = X86.ADDR_INVALID; break; } @@ -698,13 +726,13 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress) return this.base; } cpu.assert(false); - if (!fSuppress) X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, nFaultError, true); + if (this.id < X86Seg.ID.VER) X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, nFaultError, true); base = addrDesc = X86.ADDR_INVALID; break; } else if (fGate !== false) { cpu.assert(false); - if (!fSuppress) X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, true); + if (this.id < X86Seg.ID.VER) X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, true); base = addrDesc = X86.ADDR_INVALID; break; } @@ -712,7 +740,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress) else if (this.id == X86Seg.ID.DATA) { if (selMasked) { if (!(acc & X86.DESC.ACC.PRESENT)) { - if (!fSuppress) X86.fnFault.call(cpu, X86.EXCEPTION.NP_FAULT, sel); + if (this.id < X86Seg.ID.VER) X86.fnFault.call(cpu, X86.EXCEPTION.NP_FAULT, sel); base = addrDesc = X86.ADDR_INVALID; break; } @@ -738,7 +766,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress) * * So, if the ACC field is zero, we won't set the last fnFault() parameter (fHalt) to true. */ - if (!fSuppress) X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, !!acc); + if (this.id < X86Seg.ID.VER) X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, !!acc); base = addrDesc = X86.ADDR_INVALID; break; } @@ -746,12 +774,12 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress) } else if (this.id == X86Seg.ID.STACK) { if (!(acc & X86.DESC.ACC.PRESENT)) { - if (!fSuppress) X86.fnFault.call(cpu, X86.EXCEPTION.SS_FAULT, sel); + if (this.id < X86Seg.ID.VER) X86.fnFault.call(cpu, X86.EXCEPTION.SS_FAULT, sel); base = addrDesc = X86.ADDR_INVALID; break; } if (!selMasked || type < X86.DESC.ACC.TYPE.SEG || (type & (X86.DESC.ACC.TYPE.CODE | X86.DESC.ACC.TYPE.WRITABLE)) != X86.DESC.ACC.TYPE.WRITABLE) { - if (!fSuppress) X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, true); + if (this.id < X86Seg.ID.VER) X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, true); base = addrDesc = X86.ADDR_INVALID; break; } @@ -759,7 +787,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress) else if (this.id == X86Seg.ID.TSS) { var typeTSS = type & ~X86.DESC.ACC.TSS_BUSY; if (!selMasked || typeTSS != X86.DESC.ACC.TYPE.TSS286 && typeTSS != X86.DESC.ACC.TYPE.TSS386) { - if (!fSuppress) X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, true); + if (this.id < X86Seg.ID.VER) X86.fnFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, true); base = addrDesc = X86.ADDR_INVALID; break; } @@ -772,7 +800,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress) this.addrIOPMLimit = (base + this.limit)|0; } } - else if (this.id == X86Seg.ID.OTHER) { + else if (this.id == X86Seg.ID.VER) { /* * For LSL, we must support any descriptor marked X86.DESC.ACC.TYPE.SEG, as well as TSS and LDT descriptors. */ @@ -781,6 +809,9 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress) break; } } + /* + * The only other case should be X86Seg.ID.DBG, for which we do nothing. + */ this.sel = sel; this.base = base; @@ -793,7 +824,9 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress) this.updateMode(true, true, false); break; } - if (!fSuppress) this.messageSeg(sel, base, limit, type, ext); + + if (DEBUG) this.messageSeg(sel, base, limit, type, ext); + return base; }; @@ -1218,7 +1251,7 @@ X86Seg.prototype.updateMode = function(fLoad, fProt, fV86) X86Seg.prototype.messageSeg = function(sel, base, limit, type, ext) { if (DEBUG) { - if (DEBUGGER && this.dbg && this.dbg.messageEnabled(Messages.SEG)) { + if (DEBUGGER && this.id != X86Seg.ID.DBG && this.dbg && this.dbg.messageEnabled(Messages.SEG)) { var ch = (this.sName.length < 3? " " : ""); var sDPL = " dpl=" + this.dpl; if (this.id == X86Seg.ID.CODE) sDPL += " cpl=" + this.cpl;