Improved the Debugger edit command

This commit is contained in:
Jeff Parsons 2015-08-28 23:17:21 -07:00
commit b8ddedd9cf
146 changed files with 1827 additions and 1818 deletions

View file

@ -137,8 +137,7 @@ function Bus(parmsBus, cpu, dbg)
* Lists of I/O notification functions: aPortInputNotify and aPortOutputNotify are arrays, indexed by
* port, of sub-arrays which contain:
*
* [0]: registered component
* [1]: registered function to call for every I/O access
* [0]: registered function to call for every I/O access
*
* The registered function is called with the port address, and if the access was triggered by the CPU,
* the linear instruction pointer (LIP) at the point of access.
@ -148,10 +147,10 @@ function Bus(parmsBus, cpu, dbg)
* of chained functions across multiple components, but I doubt that will be necessary here.
*
* UPDATE: The Debugger now piggy-backs on these arrays to indicate ports for which it wants notification
* of I/O. In those cases, the registered component/function elements may or may not be set, but the following
* additional element will be set:
* of I/O. In those cases, the registered component/function elements may or may not be set, but the
* following additional element will be set:
*
* [2]: true to break on I/O, false to ignore I/O
* [1]: true to break on I/O, false to ignore I/O
*
* The false case is important if fPortInputBreakAll and/or fPortOutputBreakAll is set, because it allows the
* Debugger to selectively ignore specific ports.
@ -1316,33 +1315,32 @@ Bus.prototype.addPortInputBreak = function(port)
return this.fPortInputBreakAll;
}
if (this.aPortInputNotify[port] === undefined) {
this.aPortInputNotify[port] = [null, null, false];
this.aPortInputNotify[port] = [null, false];
}
this.aPortInputNotify[port][2] = !this.aPortInputNotify[port][2];
return this.aPortInputNotify[port][2];
this.aPortInputNotify[port][1] = !this.aPortInputNotify[port][1];
return this.aPortInputNotify[port][1];
};
/**
* addPortInputNotify(start, end, component, fn)
* addPortInputNotify(start, end, fn)
*
* Add a port input-notification handler to the list of such handlers.
*
* @this {Bus}
* @param {number} start port address
* @param {number} end port address
* @param {Component} component
* @param {function(number,number)} fn is called with the port and LIP values at the time of the input
*/
Bus.prototype.addPortInputNotify = function(start, end, component, fn)
Bus.prototype.addPortInputNotify = function(start, end, fn)
{
if (fn !== undefined) {
for (var port = start; port <= end; port++) {
if (this.aPortInputNotify[port] !== undefined) {
Component.warning("Input port " + str.toHexWord(port) + " registered by " + this.aPortInputNotify[port][0].id + ", ignoring " + component.id);
Component.warning("Input port " + str.toHexWord(port) + " already registered");
continue;
}
this.aPortInputNotify[port] = [component, fn, false, false];
if (MAXDEBUG) this.log("addPortInputNotify(" + str.toHexWord(port) + "," + component.id + ")");
this.aPortInputNotify[port] = [fn, false];
if (MAXDEBUG) this.log("addPortInputNotify(" + str.toHexWord(port) + ")");
}
}
};
@ -1361,7 +1359,7 @@ Bus.prototype.addPortInputTable = function(component, table, offset)
{
if (offset === undefined) offset = 0;
for (var port in table) {
this.addPortInputNotify(+port + offset, +port + offset, component, table[port]);
this.addPortInputNotify(+port + offset, +port + offset, table[port].bind(component));
}
};
@ -1373,7 +1371,7 @@ Bus.prototype.addPortInputTable = function(component, table, offset)
* @param {number} [addrLIP] is the LIP value at the time of the input
* @return {number} simulated port value (0xff if none)
*
* NOTE: It seems that at least parts of the ROM BIOS (like the RS-232 probes around F000:E5D7 in the 5150 BIOS)
* NOTE: It seems that parts of the ROM BIOS (like the RS-232 probes around F000:E5D7 in the 5150 BIOS)
* assume that ports for non-existent hardware return 0xff rather than 0x00, hence my new default (0xff) below.
*/
Bus.prototype.checkPortInputNotify = function(port, addrLIP)
@ -1385,14 +1383,14 @@ Bus.prototype.checkPortInputNotify = function(port, addrLIP)
this.cpu.backTrack.btiIO = 0;
}
if (aNotify !== undefined) {
if (aNotify[1]) {
var b = aNotify[1].call(aNotify[0], port, addrLIP);
if (aNotify[0]) {
var b = aNotify[0]( port, addrLIP);
if (b !== undefined) {
this.assert(!(b & ~0xff));
bIn = b;
}
}
if (DEBUGGER && this.dbg && this.fPortInputBreakAll != aNotify[2]) {
if (DEBUGGER && this.dbg && this.fPortInputBreakAll != aNotify[1]) {
this.dbg.checkPortInput(port, bIn);
}
}
@ -1406,21 +1404,19 @@ Bus.prototype.checkPortInputNotify = function(port, addrLIP)
};
/**
* removePortInputNotify(start, end, component, fn)
* removePortInputNotify(start, end)
*
* Remove a port input-notification handler from the list of such handlers (to be ENABLED later if needed)
* Remove port input-notification handler(s) (to be ENABLED later if needed)
*
* @this {Bus}
* @param {number} start address
* @param {number} end address
* @param {Component} component
* @param {function(number,number)} fn of previously added handler
*
Bus.prototype.removePortInputNotify = function(start, end, component, fn)
Bus.prototype.removePortInputNotify = function(start, end)
{
for (var port = start; port < end; port++) {
if (this.aPortInputNotify[port] && this.aPortInputNotify[port][0] == component && this.aPortInputNotify[port][1] == fn) {
this.aPortInputNotify[port] = undefined;
if (this.aPortInputNotify[port]) {
delete this.aPortInputNotify[port];
}
}
};
@ -1440,33 +1436,32 @@ Bus.prototype.addPortOutputBreak = function(port)
return this.fPortOutputBreakAll;
}
if (this.aPortOutputNotify[port] === undefined) {
this.aPortOutputNotify[port] = [null, null, false];
this.aPortOutputNotify[port] = [null, false];
}
this.aPortOutputNotify[port][2] = !this.aPortOutputNotify[port][2];
return this.aPortOutputNotify[port][2];
this.aPortOutputNotify[port][1] = !this.aPortOutputNotify[port][1];
return this.aPortOutputNotify[port][1];
};
/**
* addPortOutputNotify(start, end, component, fn)
* addPortOutputNotify(start, end, fn)
*
* Add a port output-notification handler to the list of such handlers.
*
* @this {Bus}
* @param {number} start port address
* @param {number} end port address
* @param {Component} component
* @param {function(number,number)} fn is called with the port and LIP values at the time of the output
*/
Bus.prototype.addPortOutputNotify = function(start, end, component, fn)
Bus.prototype.addPortOutputNotify = function(start, end, fn)
{
if (fn !== undefined) {
for (var port = start; port <= end; port++) {
if (this.aPortOutputNotify[port] !== undefined) {
Component.warning("Output port " + str.toHexWord(port) + " registered by " + this.aPortOutputNotify[port][0].id + ", ignoring " + component.id);
Component.warning("Output port " + str.toHexWord(port) + " already registered");
continue;
}
this.aPortOutputNotify[port] = [component, fn, false, false];
if (MAXDEBUG) this.log("addPortOutputNotify(" + str.toHexWord(port) + "," + component.id + ")");
this.aPortOutputNotify[port] = [fn, false];
if (MAXDEBUG) this.log("addPortOutputNotify(" + str.toHexWord(port) + ")");
}
}
};
@ -1485,7 +1480,7 @@ Bus.prototype.addPortOutputTable = function(component, table, offset)
{
if (offset === undefined) offset = 0;
for (var port in table) {
this.addPortOutputNotify(+port + offset, +port + offset, component, table[port]);
this.addPortOutputNotify(+port + offset, +port + offset, table[port].bind(component));
}
};
@ -1501,11 +1496,11 @@ Bus.prototype.checkPortOutputNotify = function(port, bOut, addrLIP)
{
var aNotify = this.aPortOutputNotify[port];
if (aNotify !== undefined) {
if (aNotify[1]) {
if (aNotify[0]) {
this.assert(!(bOut & ~0xff));
aNotify[1].call(aNotify[0], port, bOut, addrLIP);
aNotify[0](port, bOut, addrLIP);
}
if (DEBUGGER && this.dbg && this.fPortOutputBreakAll != aNotify[2]) {
if (DEBUGGER && this.dbg && this.fPortOutputBreakAll != aNotify[1]) {
this.dbg.checkPortOutput(port, bOut);
}
}
@ -1518,21 +1513,19 @@ Bus.prototype.checkPortOutputNotify = function(port, bOut, addrLIP)
};
/**
* removePortOutputNotify(start, end, component, fn)
* removePortOutputNotify(start, end)
*
* Remove a port output-notification handler from the list of such handlers (to be ENABLED later if needed)
* Remove port output-notification handler(s) (to be ENABLED later if needed)
*
* @this {Bus}
* @param {number} start address
* @param {number} end address
* @param {Component} component
* @param {function(number,number)} fn of previously added handler
*
Bus.prototype.removePortOutputNotify = function(start, end, component, fn)
Bus.prototype.removePortOutputNotify = function(start, end)
{
for (var port = start; port < end; port++) {
if (this.aPortOutputNotify[port] && this.aPortOutputNotify[port][0] == component && this.aPortOutputNotify[port][1] == fn) {
this.aPortOutputNotify[port] = undefined;
if (this.aPortOutputNotify[port]) {
delete this.aPortOutputNotify[port];
}
}
};

View file

@ -1067,7 +1067,7 @@ ChipSet.prototype.initBus = function(cmp, bus, cpu, dbg)
chipset.dumpCMOS();
});
}
cpu.addIntNotify(Interrupts.RTC, this, this.intBIOSRTC);
cpu.addIntNotify(Interrupts.RTC, this.intBIOSRTC.bind(this));
}
};

View file

@ -480,17 +480,18 @@ CPU.prototype.updateStatus = function(fForce)
};
/**
* updateVideo()
* updateVideo(fForce)
*
* Any high-frequency updates should be performed here. Avoid DOM updates, since updateVideo() can be called up to
* 60 times per second (see VIDEO_UPDATES_PER_SECOND).
*
* @this {CPU}
* @param {boolean} [fForce] (true to force a video update)
*/
CPU.prototype.updateVideo = function()
CPU.prototype.updateVideo = function(fForce)
{
for (var i = 0; i < this.aVideo.length; i++) {
this.aVideo[i].updateScreen();
this.aVideo[i].updateScreen(fForce);
}
if (this.cmp && this.cmp.panel) this.cmp.panel.updateAnimation();
};
@ -1122,7 +1123,7 @@ CPU.prototype.stopCPU = function(fComplete)
};
/**
* updateCPU()
* updateCPU(fForce)
*
* This used to be performed at the end of every stepCPU(), but runCPU() -- which relies upon
* stepCPU() -- needed to have more control over when these updates are performed. However, for
@ -1130,10 +1131,11 @@ CPU.prototype.stopCPU = function(fComplete)
* provides the old behavior.
*
* @this {CPU}
* @param {boolean} [fForce] (true to force a video update; used by the Debugger)
*/
CPU.prototype.updateCPU = function()
CPU.prototype.updateCPU = function(fForce)
{
this.updateVideo();
this.updateVideo(fForce);
this.updateStatus();
};

View file

@ -1248,11 +1248,11 @@ if (DEBUGGER) {
this.messageDump(Messages.DOS, function onDumpDOS(s) { dbg.dumpDOS(s); });
this.fWinDbg = this.dbgAddrWinDbg = null;
this.cpu.addIntNotify(Interrupts.WINDBG.VECTOR, this, this.intWindowsDebugger);
this.cpu.addIntNotify(Interrupts.WINDBG.VECTOR, this.intWindowsDebugger.bind(this));
if (Interrupts.WINDBGRM.ENABLED) {
this.fWinDbgRM = null;
this.cpu.addIntNotify(Interrupts.WINDBGRM.VECTOR, this, this.intWindowsDebuggerRM);
this.cpu.addIntNotify(Interrupts.WINDBGRM.VECTOR, this.intWindowsDebuggerRM.bind(this));
}
this.setReady();
@ -1370,7 +1370,7 @@ if (DEBUGGER) {
break;
default:
this.println("INT 0x68: " + str.toHexByte(AH));
// this.println("INT 0x68: " + str.toHexByte(AH));
break;
}
@ -1667,7 +1667,7 @@ if (DEBUGGER) {
if (addr !== X86.ADDR_INVALID) {
this.cpu.setByte(addr, b);
if (inc) this.incAddr(dbgAddr, inc);
this.cpu.updateCPU();
this.cpu.updateCPU(true); // we set fForce to true in case video memory was the target
}
};
@ -1685,7 +1685,7 @@ if (DEBUGGER) {
if (addr !== X86.ADDR_INVALID) {
this.cpu.setShort(addr, w);
if (inc) this.incAddr(dbgAddr, inc);
this.cpu.updateCPU();
this.cpu.updateCPU(true); // we set fForce to true in case video memory was the target
}
};
@ -5231,7 +5231,7 @@ if (DEBUGGER) {
this.println("\tdi [a] dump backtrack info for address a");
}
this.println("\tds [#] dump descriptor info for selector #");
if (sDumpers.length) this.println("dump extensions:\n\t" + sDumpers);
if (sDumpers.length) this.println("dump extension commands:\n\t" + sDumpers);
return;
}
@ -5354,22 +5354,41 @@ if (DEBUGGER) {
*/
Debugger.prototype.doEdit = function(asArgs)
{
var size = 1;
var mask = 0xff;
var fnGet = this.getByte;
var fnSet = this.setByte;
if (asArgs[0] == "ew") {
size = 2;
mask = 0xffff;
fnGet = this.getShort;
fnSet = this.setShort;
}
var cch = size << 1;
var sAddr = asArgs[1];
if (sAddr === undefined) {
this.println("missing address");
if (sAddr == null) {
this.println("edit memory commands:");
this.println("\teb [a] [...] edit bytes at address a");
this.println("\tew [a] [...] edit words at address a");
return;
}
var dbgAddr = this.parseAddr(sAddr, Debugger.ADDR_DATA);
if (!dbgAddr) return;
for (var i = 2; i < asArgs.length; i++) {
var b = str.parseInt(asArgs[i], 16);
if (b === undefined) {
this.println("unrecognized value: " + str.toHexByte(b));
var vNew = this.parseExpression(asArgs[i]);
if (vNew === undefined) {
this.println("unrecognized value: " + asArgs[i]);
break;
}
this.println("setting " + this.hexAddr(dbgAddr) + " to " + str.toHexByte(b));
this.setByte(dbgAddr, b, 1);
if (vNew & ~mask) {
this.println("warning: " + str.toHex(vNew) + " exceeds " + size + "-byte value");
}
var vOld = fnGet.call(this, dbgAddr);
this.println("changing " + this.hexAddr(dbgAddr) + " from 0x" + str.toHex(vOld, cch) + " to 0x" + str.toHex(vNew, cch));
fnSet.call(this, dbgAddr, vNew, size);
}
};

View file

@ -550,8 +550,8 @@ HDC.prototype.initBus = function(cmp, bus, cpu, dbg)
bus.addPortInputTable(this, this.fATC? HDC.aATCPortInput : HDC.aXTCPortInput);
bus.addPortOutputTable(this, this.fATC? HDC.aATCPortOutput : HDC.aXTCPortOutput);
cpu.addIntNotify(HDC.BIOS.INT_DISK, this, this.intBIOSDisk);
cpu.addIntNotify(HDC.BIOS.INT_DISKETTE, this, this.intBIOSDiskette);
cpu.addIntNotify(HDC.BIOS.INT_DISK, this.intBIOSDisk.bind(this));
cpu.addIntNotify(HDC.BIOS.INT_DISKETTE, this.intBIOSDiskette.bind(this));
/*
* The following code used to be performed in the HDC constructor, but now we need to wait for information

View file

@ -1601,7 +1601,7 @@ X86CPU.prototype.getChecksum = function()
};
/**
* addIntNotify(nInt, component, fn)
* addIntNotify(nInt, fn)
*
* Add an software interrupt notification handler to the CPU's list of such handlers.
*
@ -1610,18 +1610,14 @@ X86CPU.prototype.getChecksum = function()
*
* @this {X86CPU}
* @param {number} nInt
* @param {Component} component
* @param {function(number)} fn is called with the LIP value following the software interrupt
*/
X86CPU.prototype.addIntNotify = function(nInt, component, fn)
X86CPU.prototype.addIntNotify = function(nInt, fn)
{
if (fn !== undefined) {
if (this.aIntNotify[nInt] === undefined) {
this.aIntNotify[nInt] = [];
}
this.aIntNotify[nInt].push([component, fn]);
if (MAXDEBUG) this.log("addIntNotify(" + str.toHexWord(nInt) + "," + component.id + ")");
if (this.aIntNotify[nInt] === undefined) {
this.aIntNotify[nInt] = [];
}
this.aIntNotify[nInt].push(fn);
};
/**
@ -1639,7 +1635,7 @@ X86CPU.prototype.checkIntNotify = function(nInt)
var aNotify = this.aIntNotify[nInt];
if (aNotify !== undefined) {
for (var i = 0; i < aNotify.length; i++) {
if (!aNotify[i][1].call(aNotify[i][0], this.regLIP)) {
if (!aNotify[i](this.regLIP)) {
return false;
}
}