Improved the Debugger edit command
This commit is contained in:
parent
9f3c1f2a98
commit
b8ddedd9cf
146 changed files with 1827 additions and 1818 deletions
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue