Debugger improvements for DOS debugging

This commit is contained in:
Jeff Parsons 2014-11-07 15:04:25 -08:00 • committed by jeffpar
commit ebf6933536
3 changed files with 334 additions and 293 deletions

View file

@ -4087,9 +4087,9 @@ ChipSet.prototype.set8042OutPort = function(b)
/** /**
* notifyKbdData(fAvail) * notifyKbdData(fAvail)
* *
* Previously, the Keyboard would simply call setIRR() when it had some data for the keyboard controller. * In the old days of PCjs, the Keyboard component would simply call setIRR() when it had some data for the
* Now the interface is a little more nuanced, giving the ChipSet/8042 the opportunity to decide when to * keyboard controller. However, that was completely inappropriate. The sole responsibility of the Keyboard
* raise IRQ.KBD. * is to emulate an actual keyboard and notify us whenever it has some data; it doesn't mess with IRQ lines.
* *
* If there's an 8042, we check (this.b8042CmdData & ChipSet.KBC.DATA.CMD.NO_CLOCK); if NO_CLOCK is clear, * If there's an 8042, we check (this.b8042CmdData & ChipSet.KBC.DATA.CMD.NO_CLOCK); if NO_CLOCK is clear,
* we can raise the IRQ immediately. Well, not quite immediately.... * we can raise the IRQ immediately. Well, not quite immediately....
@ -4166,7 +4166,7 @@ ChipSet.prototype.notifyKbdData = function(fAvail)
{ {
if (this.model < ChipSet.MODEL_5170) { if (this.model < ChipSet.MODEL_5170) {
/* /*
* TODO: Should we be checking bPPI for PPI_B.CLK_KBD on these older machines, before called setIRR()? * TODO: Should we be checking bPPI for PPI_B.CLK_KBD on these older machines, before calling setIRR()?
*/ */
this.setIRR(ChipSet.IRQ.KBD, 4); this.setIRR(ChipSet.IRQ.KBD, 4);
} }

View file

@ -1171,7 +1171,9 @@ if (DEBUGGER) {
} }
} }
this.cpu.addIntNotify(Debugger.INT_DOS, this, this.intDOSCall); this.messageDump(Debugger.MESSAGE_DOS, function onDumpDOS(s) {
dbg.dumpDOS(s);
});
this.setReady(); this.setReady();
@ -1281,6 +1283,56 @@ if (DEBUGGER) {
if (this.controlDebug) this.controlDebug.focus(); if (this.controlDebug) this.controlDebug.focus();
}; };
/**
* dumpDOS(s)
*
* @this {Debugger}
* @param {string} [s]
*/
Debugger.prototype.dumpDOS = function(s)
{
if (!s) return;
this.println("dumpDOS(" + s + ")");
/*
* If s is provided and str.parseInt(s) succeeds, then we assume it represents a starting
* MCB (Memory Control Block) segment, and we dump the corresponding blocks.
*/
var seg = str.parseInt(s);
while (seg) {
var aAddr = this.newAddr(0, seg);
var bSig = this.getByte(aAddr, 1);
var wPID = this.getWord(aAddr, 2);
var wParas = this.getWord(aAddr, 5);
if (bSig != 0x4D && bSig != 0x5A) break;
this.println(str.toHexAddr(0, seg) + ": '" + String.fromCharCode(bSig) + "' PID=" + str.toHexWord(wPID) + " LEN=" + str.toHexWord(wParas) + ' "' + this.dumpSZ(aAddr, 8) + '"');
seg += 1 + wParas;
}
};
/**
* dumpSZ(aAddr, cchMax)
*
* Dump helper for zero-terminated strings.
*
* @this {Debugger}
* @param {Array} aAddr
* @param {number} [cchMax]
* @return {string} (and aAddr advanced past the terminating zero)
*/
Debugger.prototype.dumpSZ = function(aAddr, cchMax)
{
var sChars = "";
cchMax = cchMax || 256;
while (sChars.length < cchMax) {
var b = this.getByte(aAddr, 1);
if (!b) break;
sChars += (b >= 32 && b < 128? String.fromCharCode(b) : ".");
}
return sChars;
};
/** /**
* initMessages(sEnable) * initMessages(sEnable)
* *
@ -1373,14 +1425,21 @@ if (DEBUGGER) {
* @this {Debugger} * @this {Debugger}
* @param {number} nInt * @param {number} nInt
* @param {number} addr * @param {number} addr
* @return {boolean} true if message generated, false if not
*/ */
Debugger.prototype.messageInt = function(nInt, addr) Debugger.prototype.messageInt = function(nInt, addr)
{ {
/* /*
* TODO: Filtering of interrupt numbers below should be user-definable; this is very quick-and-dirty. * TODO: Filtering of interrupt numbers below should be user-definable; this is very quick-and-dirty.
*/ */
if (nInt != 0x10 && nInt != 0x15 && nInt != 0x16 && nInt != 0x1A && nInt != 0x1C) { var fMessage = false;
var AH = this.cpu.regAX >> 8; var AH = this.cpu.regAX >> 8;
if (this.messageEnabled(Debugger.MESSAGE_DOS)) {
fMessage = (nInt == 0x21 && AH != 0x0b);
} else {
fMessage = (nInt != 0x10 && nInt != 0x15 && nInt != 0x16 && nInt != 0x1A && nInt != 0x1C);
}
if (fMessage) {
var aFuncs = Debugger.INT_FUNCS[nInt]; var aFuncs = Debugger.INT_FUNCS[nInt];
var sFunc = (aFuncs && aFuncs[AH]) || ""; var sFunc = (aFuncs && aFuncs[AH]) || "";
if (sFunc) { if (sFunc) {
@ -1389,6 +1448,7 @@ if (DEBUGGER) {
} }
this.message("INT 0x" + str.toHexByte(nInt) + ": AH=" + str.toHexByte(AH) + " at " + str.toHexAddr(addr - this.cpu.segCS.base, this.cpu.segCS.sel) + sFunc); this.message("INT 0x" + str.toHexByte(nInt) + ": AH=" + str.toHexByte(AH) + " at " + str.toHexAddr(addr - this.cpu.segCS.base, this.cpu.segCS.sel) + sFunc);
} }
return fMessage;
}; };
/** /**
@ -1402,12 +1462,7 @@ if (DEBUGGER) {
*/ */
Debugger.prototype.messageIntReturn = function(nInt, nLevel, nCycles, sResult) Debugger.prototype.messageIntReturn = function(nInt, nLevel, nCycles, sResult)
{ {
/* this.message("INT 0x" + str.toHexByte(nInt) + ": C=" + (this.cpu.getCF()? 1 : 0) + (sResult || "") + " (cycles=" + nCycles + (nLevel? ",level=" + (nLevel+1) : "") + ")");
* TODO: Filtering of interrupt numbers below should be user-definable; this is very quick-and-dirty.
*/
if (nInt < 0x20 && nInt != 0x10 && nInt != 0x15 && nInt != 0x16 && nInt != 0x1A && nInt != 0x1C) {
this.message("INT 0x" + str.toHexByte(nInt) + "(" + nLevel + "): C=" + (this.cpu.getCF()? 1 : 0) + (sResult || "") + " (cycles=" + nCycles + ")");
}
}; };
/** /**
@ -1538,19 +1593,6 @@ if (DEBUGGER) {
} }
}; };
/**
* intDOSCall(addr)
*
* @this {Debugger}
* @param {number} addr
* @return {boolean} true to proceed with the INT 0x21 software interrupt, false to skip (but we NEVER skip)
*/
Debugger.prototype.intDOSCall = function(addr)
{
if (this.messageEnabled(Debugger.MESSAGE_DOS | Debugger.MESSAGE_INT)) this.messageInt(Debugger.INT_DOS, addr);
return true;
};
/** /**
* init() * init()
* *

View file

@ -924,11 +924,10 @@ X86CPU.prototype.checkIntNotify = function(nInt)
} }
else if (DEBUGGER && this.aFlags.fDebugCheck) { else if (DEBUGGER && this.aFlags.fDebugCheck) {
/* /*
* Enabling MESSAGE_INT messages is one of the criteria that's also included in fDebugCheck, so for maximum * Enabling MESSAGE_INT messages is one of the criteria that's also included in fDebugCheck,
* speed, we check fDebugCheck first. * so for maximum speed, we check fDebugCheck first.
*/ */
if (this.dbg.messageEnabled(Debugger.MESSAGE_INT)) { if (this.dbg.messageEnabled(Debugger.MESSAGE_INT) && this.dbg.messageInt(nInt, this.regEIP)) {
this.dbg.messageInt(nInt, this.regEIP);
this.addIntReturn(this.regEIP, function(cpu, nCycles) { this.addIntReturn(this.regEIP, function(cpu, nCycles) {
return function onIntReturn(nLevel) { return function onIntReturn(nLevel) {
cpu.dbg.messageIntReturn(nInt, nLevel, cpu.getCycles() - nCycles); cpu.dbg.messageIntReturn(nInt, nLevel, cpu.getCycles() - nCycles);