Fixed high 8-bit register MOVs, restricted ACCESSED bit updates to SEGMENT descriptors, and prevented the Debugger from looping endlessly on bad instructions

This commit is contained in:
Jeff Parsons 2015-08-20 22:42:27 -07:00
commit 2d7cbe2864
4 changed files with 33 additions and 28 deletions

View file

@ -11,7 +11,7 @@
<video ref="/devices/pc/video/ibm/vga/ibm-vga-lockfs.xml"/>
<keyboard id="keyboard"/>
<fdc ref="/disks/pc/library.xml" automount='{B: {name: "Win95 Build 499 (Disk 1)", path: "/disks/pc/windows/win95/build499/WIN95-DISK01.json"}}'/>
<debugger id="debugger" messages="fault|tss|int" commands='m dos off;bp 1ED4:16B4 "let fn=ah;dos;if fn!=3f||cx!=24"'/>
<debugger id="debugger" messages="fault|tss|int" commands='m dos off'/>
<panel ref="/devices/pc/panel/wide386.xml"/>
<hdc id="hdcAT" type="at" drives='[{name:"68Mb Hard Disk",type:4,path:"http://static.pcjs.org/devices/pc/machine/compaq/deskpro386/vga/4096kb/WDEB386-68Mb.json"}]'/>
<chipset id="chipset" model="deskpro386" floppies="[1200,1200]" monitor="vga"/>

View file

@ -1538,13 +1538,15 @@ if (DEBUGGER) {
*/
if (this.nSuppressBreaks && fProt || !this.segDebugger) return null;
}
var seg = this.segDebugger;
if (!fProt) {
this.segDebugger.loadReal(sel);
seg.loadReal(sel);
seg.limit = 0xffff; // although an ACTUAL real-mode segment load would not modify the limit,
seg.offMax = 0x10000; // proper segDebugger operation requires that we update the limit ourselves
} else {
this.segDebugger.loadProt(sel);
seg.loadProt(sel);
}
return this.segDebugger;
return seg;
};
/**
@ -2929,7 +2931,7 @@ if (DEBUGGER) {
if (!fRegs || this.nStep == 1)
this.doUnassemble();
else {
this.doRegisters(null);
this.doRegisters();
}
};
@ -3841,6 +3843,7 @@ if (DEBUGGER) {
if (dbgAddrIns.addr != X86.ADDR_INVALID && dbgAddr.addr != X86.ADDR_INVALID) {
do {
sBytes += str.toHex(this.getByte(dbgAddrIns, 1), 2);
if (dbgAddrIns.addr == null) break;
} while (dbgAddrIns.addr != dbgAddr.addr);
}

View file

@ -3079,7 +3079,7 @@ X86.opMOVBLb = function MOVBLb()
*/
X86.opMOVAHb = function MOVAHb()
{
this.regEAX = (this.regEAX & 0xff) | (this.getIPByte() << 8);
this.regEAX = (this.regEAX & ~0xff00) | (this.getIPByte() << 8);
if (BACKTRACK) this.backTrack.btiAH = this.backTrack.btiMem0;
this.nStepCycles -= this.cycleCounts.nOpCyclesLAHF;
};
@ -3091,7 +3091,7 @@ X86.opMOVAHb = function MOVAHb()
*/
X86.opMOVCHb = function MOVCHb()
{
this.regECX = (this.regECX & 0xff) | (this.getIPByte() << 8);
this.regECX = (this.regECX & ~0xff00) | (this.getIPByte() << 8);
if (BACKTRACK) this.backTrack.btiCH = this.backTrack.btiMem0;
this.nStepCycles -= this.cycleCounts.nOpCyclesLAHF;
};
@ -3103,7 +3103,7 @@ X86.opMOVCHb = function MOVCHb()
*/
X86.opMOVDHb = function MOVDHb()
{
this.regEDX = (this.regEDX & 0xff) | (this.getIPByte() << 8);
this.regEDX = (this.regEDX & ~0xff00) | (this.getIPByte() << 8);
if (BACKTRACK) this.backTrack.btiDH = this.backTrack.btiMem0;
this.nStepCycles -= this.cycleCounts.nOpCyclesLAHF;
};
@ -3115,7 +3115,7 @@ X86.opMOVDHb = function MOVDHb()
*/
X86.opMOVBHb = function MOVBHb()
{
this.regEBX = (this.regEBX & 0xff) | (this.getIPByte() << 8);
this.regEBX = (this.regEBX & ~0xff00) | (this.getIPByte() << 8);
if (BACKTRACK) this.backTrack.btiBH = this.backTrack.btiMem0;
this.nStepCycles -= this.cycleCounts.nOpCyclesLAHF;
};

View file

@ -1194,6 +1194,26 @@ X86Seg.prototype.updateMode = function(fLoad, fProt, fV86)
if (this.checkWrite == this.checkWriteProt) this.checkWrite = this.checkWriteProtDown;
this.fExpDown = true;
}
if (fLoad && this.id < X86Seg.ID.VER) {
/*
* We must update the descriptor's ACCESSED bit whenever the segment is "accessed" (ie,
* loaded); unlike the ACCESSED and DIRTY bits in PTEs, a descriptor ACCESSED bit is only
* updated on loads, not on every memory access.
*
* We compute address of the descriptor byte containing the ACCESSED bit (offset 0x5);
* note that it's perfectly normal for addrDesc to occasionally be invalid (eg, when the CPU
* is creating protected-mode-only segment registers like LDT and TSS, or when the CPU has
* transitioned from real-mode to protected-mode and new selector(s) have not been loaded yet).
*
* TODO: Note I do NOT update the ACCESSED bit for null GDT selectors, because I assume the
* hardware does not update it either. In fact, I've seen code that uses the null GDT descriptor
* for other purposes, on the assumption that that descriptor is completely unused.
*/
if ((this.sel & ~X86.SEL.RPL) && this.addrDesc !== X86.ADDR_INVALID) {
var addrType = this.addrDesc + X86.DESC.ACC.TYPE.OFFSET;
this.cpu.setByte(addrType, this.cpu.getByte(addrType) | (X86.DESC.ACC.TYPE.ACCESSED >> 8));
}
}
}
/*
* TODO: For non-SEG descriptors, are there other checks or functions we should establish?
@ -1204,24 +1224,6 @@ X86Seg.prototype.updateMode = function(fLoad, fProt, fV86)
* we're updating segment registers as part of a mode change.
*/
if (fLoad) {
/*
* We must update the descriptor's ACCESSED bit whenever the segment is "accessed" (ie,
* loaded); unlike the ACCESSED and DIRTY bits in PTEs, a descriptor ACCESSED bit is only
* updated on loads, not on every memory access.
*
* We compute address of the descriptor byte containing the ACCESSED bit (offset 0x5);
* note that it's perfectly normal for addrDesc to occasionally be invalid (eg, when the CPU
* is creating protected-mode-only segment registers like LDT and TSS, or when the CPU has
* transitioned from real-mode to protected-mode and new selector(s) have not been loaded yet).
*
* TODO: Note I do NOT update the ACCESSED bit for null GDT selectors, because I assume the
* hardware does not update it either. In fact, I've seen code that uses the null GDT descriptor
* for other purposes, on the assumption that that descriptor is completely unused.
*/
if ((this.sel & ~X86.SEL.RPL) && this.addrDesc !== X86.ADDR_INVALID) {
var addrType = this.addrDesc + X86.DESC.ACC.TYPE.OFFSET;
this.cpu.setByte(addrType, this.cpu.getByte(addrType) | (X86.DESC.ACC.TYPE.ACCESSED >> 8));
}
this.cpl = this.sel & X86.SEL.RPL;
this.dpl = (this.acc & X86.DESC.ACC.DPL.MASK) >> X86.DESC.ACC.DPL.SHIFT;
if (this.cpu.model < X86.MODEL_80386 || !(this.ext & X86.DESC.EXT.BIG)) {