Some improvements to Debugger message support

This commit is contained in:
Jeff Parsons 2014-10-15 16:14:54 -07:00 committed by jeffpar
commit ba5f2fe41b
15 changed files with 1429 additions and 1285 deletions

View file

@ -108,7 +108,7 @@ function X86CPU(parmsCPU) {
this.initProcessor();
/*
* List of software interrupt notification functions: aInterruptNotify is an array, indexed by
* List of software interrupt notification functions: aIntNotify is an array, indexed by
* interrupt number, of 2-element sub-arrays that, in turn, contain:
*
* [0]: registered component
@ -122,22 +122,29 @@ function X86CPU(parmsCPU) {
* "INT 0x00" generated by a divide-by-zero or any other kind of interrupt (nor any interrupt simulated
* with "PUSHF/CALLF").
*
* aInterruptReturn is a hash of return address notifications set up by software interrupt notification
* aIntReturn is a hash of return address notifications set up by software interrupt notification
* functions that want to receive return notifications. A software interrupt function must call
* cpu.addInterruptReturn(fn).
* cpu.addIntReturn(fn).
*
* WARNING: There's no mechanism in place to insure that software interrupt return notifications don't
* get "orphaned" if an interrupt handler bypasses the normal return path (INT 0x24 is one example of an
* "evil" software interrupt).
*/
this.aInterruptNotify = [];
this.aInterruptReturn = [];
this.aIntNotify = [];
this.aIntReturn = [];
/*
* Since aReturnNotify is a "sparse array", this global count gives the CPU a quick way of knowing whether
* or not RETF or IRET instructions need to bother calling checkInterruptReturn().
* or not RETF or IRET instructions need to bother calling checkIntReturn().
*/
this.cInterruptReturn = 0;
this.cIntReturn = 0;
/*
* A variety of stepCPU() state variables that don't strictly need to be initialized before the first
* stepCPU() call, but it's good form to do so.
*/
this.nBurstCycles = 0;
this.fComplete = this.fDebugCheck = false;
/*
* We're just declaring aMemBlocks and associated Bus parameters here; they'll be initialized by initMemory()
@ -871,7 +878,7 @@ X86CPU.prototype.getChecksum = function()
};
/**
* addInterruptNotify(nInt, component, fn)
* addIntNotify(nInt, component, fn)
*
* Add an software interrupt notification handler to the CPU's list of such handlers.
*
@ -880,29 +887,47 @@ X86CPU.prototype.getChecksum = function()
* @param {Component} component
* @param {function(number)} fn is called with the EIP value following the software interrupt
*/
X86CPU.prototype.addInterruptNotify = function(nInt, component, fn)
X86CPU.prototype.addIntNotify = function(nInt, component, fn)
{
if (fn !== undefined) {
if (this.aInterruptNotify[nInt] === undefined)
this.aInterruptNotify[nInt] = [];
this.aInterruptNotify[nInt].push([component, fn]);
if (MAXDEBUG) this.log("addInterruptNotify(" + str.toHexWord(nInt) + "," + component.id + ")");
if (this.aIntNotify[nInt] === undefined) {
this.aIntNotify[nInt] = [];
}
this.aIntNotify[nInt].push([component, fn]);
if (MAXDEBUG) this.log("addIntNotify(" + str.toHexWord(nInt) + "," + component.id + ")");
}
};
/**
* checkInterruptNotify(nInt)
* checkIntNotify(nInt)
*
* NOTE: This is called only for "INT N" instructions, not "INT 3" or "INTO" or the "INT 0x00" generated by a
* divide-by-zero or any other kind of interrupt or simulation thereof (eg, "PUSHF/CALLF").
* NOTE: This is called ONLY for "INT N" instructions -- not "INTO" or breakpoint or single-step interrupts
* or divide exception interrupts, or hardware interrupts, or any simulation of an interrupt (eg, "PUSHF/CALLF").
*
* @this {X86CPU}
* @param {number} nInt
* @return {boolean} true if software interrupt may proceed, false if software interrupt should be skipped
*/
X86CPU.prototype.checkInterruptNotify = function(nInt)
X86CPU.prototype.checkIntNotify = function(nInt)
{
var aNotify = this.aInterruptNotify[nInt];
/*
* Enabling MESSAGE_INT messages is one of the criteria that's also included in fDebugCheck, so for maximum
* speed, check fDebugCheck first.
*/
if (DEBUGGER && this.fDebugCheck) {
/*
* TODO: Filtering out the hard-coded interrupt numbers below should be optional; this is very quick-and-dirty.
*/
if (nInt < 0x20 && nInt != 0x10 && nInt != 0x16 && nInt != 0x1C && this.dbg.messageEnabled(this.dbg.MESSAGE_INT)) {
this.dbg.messageInt(nInt, this.regEIP);
this.addIntReturn(this.regEIP, function(cpu, nCycles) {
return function onIntReturn(nLevel) {
cpu.dbg.messageIntReturn(nInt, nLevel, cpu.getCycles() - nCycles);
};
}(this, this.getCycles()));
}
}
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.regEIP)) {
@ -914,7 +939,7 @@ X86CPU.prototype.checkInterruptNotify = function(nInt)
};
/**
* addInterruptReturn(addr, fn)
* addIntReturn(addr, fn)
*
* Add a return notification handler to the CPU's list of such handlers.
*
@ -929,31 +954,31 @@ X86CPU.prototype.checkInterruptNotify = function(nInt)
* @param {number} addr is a physical (non-segmented) address
* @param {function(number)} fn is an interrupt-return notification function
*/
X86CPU.prototype.addInterruptReturn = function(addr, fn)
X86CPU.prototype.addIntReturn = function(addr, fn)
{
if (fn !== undefined) {
if (this.aInterruptReturn[addr] == null) {
this.cInterruptReturn++;
if (this.aIntReturn[addr] == null) {
this.cIntReturn++;
}
this.aInterruptReturn[addr] = fn;
this.aIntReturn[addr] = fn;
}
};
/**
* checkInterruptReturn(addr)
* checkIntReturn(addr)
*
* It is expected (though not required) that callers will check cInterruptReturn and avoid calling
* It is expected (though not required) that callers will check cIntReturn and avoid calling
* this function if the count is zero.
*
* @this {X86CPU}
* @param {number} addr is a physical (non-segmented) address
*/
X86CPU.prototype.checkInterruptReturn = function(addr)
X86CPU.prototype.checkIntReturn = function(addr)
{
var fn = this.aInterruptReturn[addr];
var fn = this.aIntReturn[addr];
if (fn != null) {
fn(--this.cInterruptReturn);
delete this.aInterruptReturn[addr];
fn(--this.cIntReturn);
delete this.aIntReturn[addr];
}
};