Lots o' Debugger changes, including support for breakpoint commands and logical expressions
A new "if" command for use within breakpoint commands makes it possible to conditionally halt execution now
This commit is contained in:
parent
a9b5813303
commit
2fd9f6cfe5
4 changed files with 505 additions and 355 deletions
|
|
@ -792,18 +792,23 @@ CPU.prototype.getSpeedTarget = function()
|
||||||
* @this {CPU}
|
* @this {CPU}
|
||||||
* @param {number} [nMultiplier] is the new proposed multiplier (reverts to 1 if the target was too high)
|
* @param {number} [nMultiplier] is the new proposed multiplier (reverts to 1 if the target was too high)
|
||||||
* @param {boolean} [fOnClick] is true if called from a click handler that might have stolen focus
|
* @param {boolean} [fOnClick] is true if called from a click handler that might have stolen focus
|
||||||
|
* @return {boolean} true if successful, false if not
|
||||||
* @desc Whenever the speed is changed, the running cycle count and corresponding start time must be reset,
|
* @desc Whenever the speed is changed, the running cycle count and corresponding start time must be reset,
|
||||||
* so that the next effective speed calculation obtains sensible results. In fact, when runCPU() initially calls
|
* so that the next effective speed calculation obtains sensible results. In fact, when runCPU() initially calls
|
||||||
* setSpeed() with no parameters, that's all this function does (it doesn't change the current speed setting).
|
* setSpeed() with no parameters, that's all this function does (it doesn't change the current speed setting).
|
||||||
*/
|
*/
|
||||||
CPU.prototype.setSpeed = function(nMultiplier, fOnClick)
|
CPU.prototype.setSpeed = function(nMultiplier, fOnClick)
|
||||||
{
|
{
|
||||||
|
var fSuccess = false;
|
||||||
if (nMultiplier !== undefined) {
|
if (nMultiplier !== undefined) {
|
||||||
/*
|
/*
|
||||||
* If we couldn't reach at least 80% (0.8) of the current target speed,
|
* If we haven't reached 80% (0.8) of the current target speed, revert to a multiplier of one (1).
|
||||||
* then revert the multiplier back to one.
|
|
||||||
*/
|
*/
|
||||||
if (this.aCounts.mhz / this.aCounts.mhzTarget < 0.8) nMultiplier = 1;
|
if (this.aCounts.mhz / this.aCounts.mhzTarget < 0.8) {
|
||||||
|
nMultiplier = 1;
|
||||||
|
} else {
|
||||||
|
fSuccess = true;
|
||||||
|
}
|
||||||
this.aCounts.nCyclesMultiplier = nMultiplier;
|
this.aCounts.nCyclesMultiplier = nMultiplier;
|
||||||
var mhz = this.aCounts.mhzDefault * this.aCounts.nCyclesMultiplier;
|
var mhz = this.aCounts.mhzDefault * this.aCounts.nCyclesMultiplier;
|
||||||
if (this.aCounts.mhzTarget != mhz) {
|
if (this.aCounts.mhzTarget != mhz) {
|
||||||
|
|
@ -820,6 +825,7 @@ CPU.prototype.setSpeed = function(nMultiplier, fOnClick)
|
||||||
this.aCounts.msStartRun = usr.getTime();
|
this.aCounts.msStartRun = usr.getTime();
|
||||||
this.aCounts.msEndThisRun = 0;
|
this.aCounts.msEndThisRun = 0;
|
||||||
this.calcCycles();
|
this.calcCycles();
|
||||||
|
return fSuccess;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -59,6 +59,48 @@ var X86 = {
|
||||||
*/
|
*/
|
||||||
ADDR_INVALID: -1,
|
ADDR_INVALID: -1,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Processor Exception Interrupts
|
||||||
|
*
|
||||||
|
* Of the following exceptions, all are designed to be restartable, except for 0x08 and 0x09 (and 0x0D
|
||||||
|
* after an attempt to write to a read-only segment).
|
||||||
|
*
|
||||||
|
* Error codes are pushed onto the stack for 0x08 (always 0) and 0x0A through 0x0D.
|
||||||
|
*
|
||||||
|
* Priority: Instruction exception, TRAP, NMI, Processor Extension Segment Overrun, and finally INTR.
|
||||||
|
*
|
||||||
|
* All exceptions can also occur in real-mode, except where noted. A GP_FAULT in real-mode can be triggered
|
||||||
|
* by "any memory reference instruction that attempts to reference [a] 16-bit word at offset 0FFFFH".
|
||||||
|
*
|
||||||
|
* Interrupts beyond 0x10 (up through 0x1F) are reserved for future exceptions.
|
||||||
|
*
|
||||||
|
* Implementation Detail: For any opcode we know must generate a UD_FAULT interrupt, we invoke opInvalid(),
|
||||||
|
* NOT opUndefined(). UD_FAULT is for INVALID opcodes, Intel's choice of term "undefined" notwithstanding.
|
||||||
|
*
|
||||||
|
* We reserve the term "undefined" for opcodes that require more investigation, and we invoke opUndefined()
|
||||||
|
* ONLY until an opcode's behavior has finally been defined, at which point it becomes either valid or invalid.
|
||||||
|
* The term "illegal" seems completely superfluous; we don't need a third way of describing invalid opcodes.
|
||||||
|
*
|
||||||
|
* The term "undocumented" should be limited to operations that are valid but Intel simply never documented.
|
||||||
|
*/
|
||||||
|
EXCEPTION: {
|
||||||
|
DIV_ERR: 0x00, // Divide Error Interrupt
|
||||||
|
DEBUG: 0x01, // Debug (aka Single Step Trap) Interrupt
|
||||||
|
NMI: 0x02, // Non-Maskable Interrupt
|
||||||
|
BREAKPOINT: 0x03, // Breakpoint Interrupt
|
||||||
|
OVERFLOW: 0x04, // INTO Overflow Interrupt (FYI, return address does NOT point to offending instruction)
|
||||||
|
BOUND_ERR: 0x05, // BOUND Error Interrupt
|
||||||
|
UD_FAULT: 0x06, // Invalid (aka Undefined or Illegal) Opcode (see implementation detail above)
|
||||||
|
NM_FAULT: 0x07, // No Math Unit Available (see ESC or WAIT)
|
||||||
|
DF_FAULT: 0x08, // Double Fault (see LIDT)
|
||||||
|
MP_FAULT: 0x09, // Math Unit Protection Fault (see ESC)
|
||||||
|
TS_FAULT: 0x0A, // Invalid Task State Segment Fault (protected-mode only)
|
||||||
|
NP_FAULT: 0x0B, // Not Present Fault (protected-mode only)
|
||||||
|
SS_FAULT: 0x0C, // Stack Fault (protected-mode only)
|
||||||
|
GP_FAULT: 0x0D, // General Protection Fault
|
||||||
|
PG_FAULT: 0x0E, // Page Fault
|
||||||
|
MF_FAULT: 0x10 // Math Fault (see ESC or WAIT)
|
||||||
|
},
|
||||||
/*
|
/*
|
||||||
* Processor Status flag definitions (stored in regPS)
|
* Processor Status flag definitions (stored in regPS)
|
||||||
*/
|
*/
|
||||||
|
|
@ -284,48 +326,6 @@ var X86 = {
|
||||||
TASK_LDT: 0x60,
|
TASK_LDT: 0x60,
|
||||||
TASK_IOPM: 0x64 // (not in TSS286)
|
TASK_IOPM: 0x64 // (not in TSS286)
|
||||||
},
|
},
|
||||||
/*
|
|
||||||
* Processor Exception Interrupts
|
|
||||||
*
|
|
||||||
* Of the following exceptions, all are designed to be restartable, except for 0x08 and 0x09 (and 0x0D
|
|
||||||
* after an attempt to write to a read-only segment).
|
|
||||||
*
|
|
||||||
* Error codes are pushed onto the stack for 0x08 (always 0) and 0x0A through 0x0D.
|
|
||||||
*
|
|
||||||
* Priority: Instruction exception, TRAP, NMI, Processor Extension Segment Overrun, and finally INTR.
|
|
||||||
*
|
|
||||||
* All exceptions can also occur in real-mode, except where noted. A GP_FAULT in real-mode can be triggered
|
|
||||||
* by "any memory reference instruction that attempts to reference [a] 16-bit word at offset 0FFFFH".
|
|
||||||
*
|
|
||||||
* Interrupts beyond 0x10 (up through 0x1F) are reserved for future exceptions.
|
|
||||||
*
|
|
||||||
* Implementation Detail: For any opcode we know must generate a UD_FAULT interrupt, we invoke opInvalid(),
|
|
||||||
* NOT opUndefined(). UD_FAULT is for INVALID opcodes, Intel's choice of term "undefined" notwithstanding.
|
|
||||||
*
|
|
||||||
* We reserve the term "undefined" for opcodes that require more investigation, and we invoke opUndefined()
|
|
||||||
* ONLY until an opcode's behavior has finally been defined, at which point it becomes either valid or invalid.
|
|
||||||
* The term "illegal" seems completely superfluous; we don't need a third way of describing invalid opcodes.
|
|
||||||
*
|
|
||||||
* The term "undocumented" should be limited to operations that are valid but Intel simply never documented.
|
|
||||||
*/
|
|
||||||
EXCEPTION: {
|
|
||||||
DIV_ERR: 0x00, // Divide Error Interrupt
|
|
||||||
DEBUG: 0x01, // Debug (aka Single Step Trap) Interrupt
|
|
||||||
NMI: 0x02, // Non-Maskable Interrupt
|
|
||||||
BREAKPOINT: 0x03, // Breakpoint Interrupt
|
|
||||||
OVERFLOW: 0x04, // INTO Overflow Interrupt (FYI, return address does NOT point to offending instruction)
|
|
||||||
BOUND_ERR: 0x05, // BOUND Error Interrupt
|
|
||||||
UD_FAULT: 0x06, // Invalid (aka Undefined or Illegal) Opcode (see implementation detail above)
|
|
||||||
NM_FAULT: 0x07, // No Math Unit Available (see ESC or WAIT)
|
|
||||||
DF_FAULT: 0x08, // Double Fault (see LIDT)
|
|
||||||
MP_FAULT: 0x09, // Math Unit Protection Fault (see ESC)
|
|
||||||
TS_FAULT: 0x0A, // Invalid Task State Segment Fault (protected-mode only)
|
|
||||||
NP_FAULT: 0x0B, // Not Present Fault (protected-mode only)
|
|
||||||
SS_FAULT: 0x0C, // Stack Fault (protected-mode only)
|
|
||||||
GP_FAULT: 0x0D, // General Protection Fault
|
|
||||||
PG_FAULT: 0x0E, // Page Fault
|
|
||||||
MF_FAULT: 0x10 // Math Fault (see ESC or WAIT)
|
|
||||||
},
|
|
||||||
ERRCODE: {
|
ERRCODE: {
|
||||||
EXT: 0x0001,
|
EXT: 0x0001,
|
||||||
IDT: 0x0002,
|
IDT: 0x0002,
|
||||||
|
|
|
||||||
|
|
@ -3846,7 +3846,7 @@ X86.fnFaultMessage = function(nFault, nError, fHalt)
|
||||||
fHalt = false;
|
fHalt = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (nFault == X86.EXCEPTION.GP_FAULT && this.model == X86.MODEL_80386 /* || nFault == X86.EXCEPTION.NP_FAULT && bOpcode == 0x8E */) {
|
if (nFault == X86.EXCEPTION.SS_FAULT || nFault == X86.EXCEPTION.GP_FAULT && this.model == X86.MODEL_80386 /* || nFault == X86.EXCEPTION.NP_FAULT && bOpcode == 0x8E */) {
|
||||||
fHalt = true;
|
fHalt = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue