Some debugging improvements

This commit is contained in:
Jeff Parsons 2014-11-22 09:31:15 -08:00 committed by jeffpar
commit a72d824548
7 changed files with 81 additions and 25 deletions

View file

@ -1391,9 +1391,9 @@ ChipSet.prototype.updateRTCTime = function()
if (DEBUG) {
if (nCyclesUpdate - this.nRTCCyclesNextUpdate > this.nRTCCyclesPerPeriod) {
if (bPrev & ChipSet.CMOS.STATUSC.PF) {
this.messageDebugger("RTC interrupt handler failed to clear STATUSC", Debugger.MESSAGE.RTC | Debugger.MESSAGE.WARN);
this.messageDebugger("RTC interrupt handler failed to clear STATUSC", Debugger.MESSAGE.RTC);
} else {
this.messageDebugger("CPU took too long trigger new RTC periodic interrupt", Debugger.MESSAGE.RTC | Debugger.MESSAGE.WARN);
this.messageDebugger("CPU took too long trigger new RTC periodic interrupt", Debugger.MESSAGE.RTC);
}
}
}
@ -2216,7 +2216,7 @@ ChipSet.prototype.dumpPIC = function()
sDump += " IC" + (i + 1) + "=" + str.toHexByte(b);
}
sDump += " IMR=" + str.toHexByte(pic.bIMR) + " IRR=" + str.toHexByte(pic.bIRR) + " ISR=" + str.toHexByte(pic.bISR);
this.dbg.message(sDump);
this.dbg.println(sDump);
}
}
};
@ -2240,7 +2240,7 @@ ChipSet.prototype.dumpTimer = function()
}
}
sDump += " mode=" + timer.mode + " bytes=" + timer.countBytes + " count=" + str.toHexWord(count);
this.dbg.message(sDump);
this.dbg.println(sDump);
}
}
};
@ -2259,7 +2259,7 @@ ChipSet.prototype.dumpCMOS = function()
if (sDump) sDump += '\n';
sDump += "CMOS[0x" + str.toHexByte(iCMOS) + "]: 0x" + str.toHexByte(b);
}
this.dbg.message(sDump);
this.dbg.println(sDump);
}
};
@ -2738,7 +2738,7 @@ ChipSet.prototype.advanceDMA = function(channel, fInit)
var addr = (channel.bPage << 16) | (channel.addrCurrent[1] << 8) | channel.addrCurrent[0];
if (DEBUG && DEBUGGER && channel.sAddrDebug === null) {
channel.sAddrDebug = str.toHex(addr >> 4, 4) + ":" + str.toHex(addr & 0xf, 4);
if (this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.DMA | (iDMAChannel == ChipSet.DMA_FDC? Debugger.MESSAGE.FDC : (iDMAChannel == ChipSet.DMA_HDC? Debugger.MESSAGE.HDC : Debugger.MESSAGE.LOG))) && channel.xfer != ChipSet.DMA_MODE.XFER_WRITE) {
if (this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.DMA | (iDMAChannel == ChipSet.DMA_FDC? Debugger.MESSAGE.FDC : (iDMAChannel == ChipSet.DMA_HDC? Debugger.MESSAGE.HDC : 0))) && channel.xfer != ChipSet.DMA_MODE.XFER_WRITE) {
this.dbg.message("advanceDMA(" + iDMAChannel + ") transferring " + channel.cbDebug + " bytes from " + channel.sAddrDebug);
this.dbg.doDump("db", channel.sAddrDebug, "l" + Math.floor((channel.cbDebug + 15) / 16));
}
@ -2848,7 +2848,7 @@ ChipSet.prototype.updateDMA = function(channel)
channel.component = channel.obj = null;
}
if (DEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.DMA | (iDMAChannel == ChipSet.DMA_FDC? Debugger.MESSAGE.FDC : (iDMAChannel == ChipSet.DMA_HDC? Debugger.MESSAGE.HDC : Debugger.MESSAGE.LOG))) && channel.xfer == ChipSet.DMA_MODE.XFER_WRITE && channel.sAddrDebug) {
if (DEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.DMA | (iDMAChannel == ChipSet.DMA_FDC? Debugger.MESSAGE.FDC : (iDMAChannel == ChipSet.DMA_HDC? Debugger.MESSAGE.HDC : 0))) && channel.xfer == ChipSet.DMA_MODE.XFER_WRITE && channel.sAddrDebug) {
this.dbg.message("updateDMA(" + iDMAChannel + ") transferred " + channel.cbDebug + " bytes to " + channel.sAddrDebug);
this.dbg.doDump("db", channel.sAddrDebug, "l" + Math.floor((channel.cbDebug + 15) / 16));
}
@ -3721,7 +3721,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
}
}
if (DEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.TIMER)) {
if (DEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.TIMER | Debugger.MESSAGE.LOG)) {
this.log("TIMER" + iTimer + " count: " + count + ", ticks: " + ticks + ", fired: " + (fFired? "true" : "false"));
}
@ -4090,7 +4090,7 @@ ChipSet.prototype.in8042RWReg = function(port, addrFrom)
* Thanks to the WAITF function, this has become a very "busy" port, so let's not generate messages
* unless both MESSAGE_8042 *and* MESSAGE_LOG are set.
*/
this.messagePort(port, null, addrFrom, "8042_RWREG", Debugger.MESSAGE.C8042 | Debugger.MESSAGE.LOG, b);
this.messagePort(port, null, addrFrom, "8042_RWREG", Debugger.MESSAGE.C8042, b);
return b;
};
@ -4670,7 +4670,7 @@ ChipSet.prototype.messageDebugger = function(sMessage, bitsMessage, nIRQ)
bitsMessage = Debugger.MESSAGE.CHIPSET;
}
if (nIRQ !== undefined) {
bitsMessage |= (nIRQ == ChipSet.IRQ.TIMER0? Debugger.MESSAGE.TIMER : (nIRQ == ChipSet.IRQ.KBD? Debugger.MESSAGE.KBD : (nIRQ == ChipSet.IRQ.FDC? Debugger.MESSAGE.FDC : Debugger.MESSAGE.PIC)));
bitsMessage |= (nIRQ == ChipSet.IRQ.TIMER0? Debugger.MESSAGE.TIMER : (nIRQ == ChipSet.IRQ.KBD? Debugger.MESSAGE.KBD : (nIRQ == ChipSet.IRQ.FDC? Debugger.MESSAGE.FDC : 0))) | Debugger.MESSAGE.PIC;
}
if (this.dbg.messageEnabled(bitsMessage)) this.dbg.message(sMessage);
}

View file

@ -956,7 +956,7 @@ CPU.prototype.calcRemainingTime = function()
this.aCounts.nCyclesRecalc += this.aCounts.nCyclesThisRun;
if (DEBUG && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.LOG) && msRemainsThisRun) {
this.dbg.message("calcRemainingTime: " + msRemainsThisRun + "ms to sleep after " + this.aCounts.msEndThisRun + "ms");
this.log("calcRemainingTime: " + msRemainsThisRun + "ms to sleep after " + this.aCounts.msEndThisRun + "ms");
}
this.aCounts.msEndThisRun += msRemainsThisRun;

View file

@ -1738,7 +1738,7 @@ if (DEBUGGER) {
{
if (this.sMessagePrev && sMessage == this.sMessagePrev) return;
this.println(sMessage); // + " (" + this.cpu.getCycles() + " cycles)"
if (!SAMPLER) this.println(sMessage); // + " (" + this.cpu.getCycles() + " cycles)"
this.sMessagePrev = sMessage;
@ -1931,7 +1931,7 @@ if (DEBUGGER) {
*/
Debugger.prototype.stopCPU = function(s)
{
if (s) this.message(s);
if (s) this.println(s);
this.cpu.stopCPU();
};
@ -4138,7 +4138,7 @@ if (DEBUGGER) {
if (sCategory !== undefined) {
var bitsMessage = 0;
if (sCategory == "all") {
bitsMessage = 0xffffffff & ~Debugger.MESSAGE.HALT;
bitsMessage = 0xffffffff & ~(Debugger.MESSAGE.HALT | Debugger.MESSAGE.LOG);
sCategory = null;
} else if (sCategory == "on") {
fCriteria = true;

View file

@ -105,6 +105,13 @@ var FATARRAYS = false;
*/
var TYPEDARRAYS = false; // (typeof ArrayBuffer !== 'undefined');
/**
* @define {boolean}
*
* Enable instruction sampling (work-in-progress).
*/
var SAMPLER = false;
if (typeof module !== 'undefined') {
global.PCJSCLASS = PCJSCLASS;
global.DEBUGGER = DEBUGGER;

View file

@ -2183,7 +2183,7 @@ FDC.prototype.doRead = function(drive)
*/
drive.resCode = FDC.REG_DATA.RES.NOT_READY | FDC.REG_DATA.RES.INCOMPLETE;
if (DEBUG) this.messageDebugger("FDC.doRead(" + drive.bCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")");
if (DEBUG) this.messageDebugger("FDC.doRead(" + drive.bCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")", Debugger.MESSAGE.OTHER);
if (drive.disk) {
drive.sector = null;
@ -2205,7 +2205,7 @@ FDC.prototype.doWrite = function(drive)
{
drive.resCode = FDC.REG_DATA.RES.NOT_READY | FDC.REG_DATA.RES.INCOMPLETE;
if (DEBUG) this.messageDebugger("FDC.doWrite(" + drive.bCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")");
if (DEBUG) this.messageDebugger("FDC.doWrite(" + drive.bCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")", Debugger.MESSAGE.OTHER);
if (drive.disk) {
if (drive.disk.fWriteProtected) {

View file

@ -1766,7 +1766,7 @@ Card.prototype.dumpCard = function()
}
if (this.iCard == Video.CARDS.EGA) {
this.dbg.message(" ATCDATA: " + this.fATCData);
this.dbg.println(" ATCDATA: " + this.fATCData);
this.dumpRegs(" ATC", this.iATCReg, this.aATCRegs, this.asATCRegs);
this.dumpRegs(" GRC", this.iGRCReg, this.aGRCRegs, this.asGRCRegs);
this.dumpRegs(" SEQ", this.iSEQReg, this.aSEQRegs, this.asSEQRegs);
@ -1774,8 +1774,8 @@ Card.prototype.dumpCard = function()
this.dumpRegs(" MISC", this.miscReg);
this.dumpRegs(" STATUS0", this.status0);
this.dumpRegs(" LATCHES", this.latches);
this.dbg.message(" ACCESS: " + str.toHexWord(this.nAccess));
this.dbg.message("Use 'dump video buffer' to dump video memory");
this.dbg.println(" ACCESS: " + str.toHexWord(this.nAccess));
this.dbg.println("Use 'dump video buffer' to dump video memory");
/*
* There are few more EGA regs we could dump, like GRCPos1, GRCPos2, but does anyone care?
*/
@ -1793,7 +1793,7 @@ Card.prototype.dumpBuffer = function(sParm)
{
if (DEBUGGER) {
if (!this.adwMemory) {
this.dbg.message("no buffer");
this.dbg.println("no buffer");
return;
}
var idw = str.parseInt(sParm);
@ -1809,7 +1809,7 @@ Card.prototype.dumpBuffer = function(sParm)
if (sDump) sDump += "\n";
sDump += sData;
}
if (sDump) this.dbg.message(sDump);
if (sDump) this.dbg.println(sDump);
this.prevDump = idw;
}
};
@ -1830,7 +1830,7 @@ Card.prototype.dumpRegs = function(sName, iReg, aRegs, asRegs)
{
if (DEBUGGER) {
if (!aRegs) {
this.dbg.message(sName + ": " + str.toHexByte(iReg));
this.dbg.println(sName + ": " + str.toHexByte(iReg));
return;
}
var s = "", i, cchMax = 0;
@ -1842,7 +1842,7 @@ Card.prototype.dumpRegs = function(sName, iReg, aRegs, asRegs)
if (s) s += '\n';
s += sName + "[" + str.toHexByte(i) + "]: " + str.pad(asRegs[i], cchMax) + str.toHexByte(aRegs[i]) + (i === iReg? "*" : "");
}
this.dbg.message(s);
this.dbg.println(s);
}
};
@ -4984,14 +4984,14 @@ Video.prototype.dumpVideo = function(sParm)
{
if (DEBUGGER) {
if (!this.cardActive) {
this.dbg.message("no active video card");
this.dbg.println("no active video card");
return;
}
if (sParm) {
this.cardActive.dumpBuffer(sParm);
return;
}
this.dbg.message("BIOSMODE: " + str.toHexByte(this.nMode));
this.dbg.println("BIOSMODE: " + str.toHexByte(this.nMode));
this.cardActive.dumpCard();
}
};

View file

@ -158,6 +158,20 @@ function X86CPU(parmsCPU) {
*/
this.setMemoryEnabled();
if (SAMPLER) {
/*
* For now, we're just going to sample EIP values
*/
this.nSamples = 50000;
this.nSampleFreq = 1;
this.nSampleSkip = 3183300;
this.aSamples = new Array(this.nSamples);
for (var i = 0; i < this.nSamples; i++) this.aSamples[i] = -1;
this.iSampleNext = 0;
this.iSampleFreq = 0;
this.iSampleSkip = 0;
}
/*
* This initial resetRegs() call is important to create all the registers (eg, the X86Seg registers),
* so that if/when we call restore(), it will have something to fill in.
@ -741,6 +755,12 @@ X86CPU.prototype.reset = function()
this.resetRegs();
this.resetCycles();
this.clearError(); // clear any fatal error/exception that setError() may have flagged
if (SAMPLER) {
this.iSampleNext = 0;
this.iSampleFreq = 0;
this.iSampleSkip = 0;
}
};
/**
@ -2526,6 +2546,35 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
fDebugSkip = false;
}
if (SAMPLER) {
if (++this.iSampleFreq >= this.nSampleFreq) {
this.iSampleFreq = 0;
if (this.iSampleSkip < this.nSampleSkip) {
this.iSampleSkip++
} else {
if (this.iSampleNext == this.nSamples) {
this.println("sample buffer full");
this.stopCPU();
break;
}
var n = this.aSamples[this.iSampleNext];
if (n !== -1) {
if (n !== this.regEIP) {
this.println("sample deviation at index " + this.iSampleNext + ": current EIP=" + str.toHex(this.regEIP) + ", target EIP=" + str.toHex(n));
this.stopCPU();
break;
}
} else {
this.aSamples[this.iSampleNext] = this.regEIP;
}
if (this.iSampleNext == 112) {
fDebugSkip = false; // just some no-op statement we can set a breakpoint on
}
this.iSampleNext++;
}
}
}
this.opFlags = 0;
if (DEBUG || PREFETCH) {