Allow the Debugger to step over "ADD [BX+SI],AL" in the rare case that it's valid
This commit is contained in:
parent
6029f8ab9a
commit
8218e1a7da
2 changed files with 27 additions and 20 deletions
|
|
@ -49,8 +49,8 @@ if (!I386) {
|
||||||
/*
|
/*
|
||||||
* These are the original ModRM decoders, which were simpler and faster because they could treat all
|
* These are the original ModRM decoders, which were simpler and faster because they could treat all
|
||||||
* word instructions as 16-bit, assume bits 16-31 of all registers were always zero, and use masking
|
* word instructions as 16-bit, assume bits 16-31 of all registers were always zero, and use masking
|
||||||
* constants instead of variables. If I386 is enabled, these decoders are not used, and the compiler
|
* constants instead of variables. If I386 is enabled, these decoders are not used, and the Closure
|
||||||
* will eliminate them from the compiled code.
|
* Compiler will eliminate them from the compiled JavaScript code.
|
||||||
*/
|
*/
|
||||||
if (NODE) {
|
if (NODE) {
|
||||||
var X86ModB = require("./x86modb");
|
var X86ModB = require("./x86modb");
|
||||||
|
|
@ -814,7 +814,7 @@ X86CPU.prototype.enablePageBlocks = function()
|
||||||
* Note that since the incoming address (addr) is a linear address, we never need to mask it with nBusMask,
|
* Note that since the incoming address (addr) is a linear address, we never need to mask it with nBusMask,
|
||||||
* but all the intermediate (PDE, PTE) and final physical addresses we calculate should still be masked.
|
* but all the intermediate (PDE, PTE) and final physical addresses we calculate should still be masked.
|
||||||
*
|
*
|
||||||
* Granted, nBusMask on a 32-bit bus is generally going to be 0xffffffff (-1), so making might seem like
|
* Granted, nBusMask on a 32-bit bus is generally going to be 0xffffffff (-1), so masking might seem like
|
||||||
* a waste of time; however, if we decide to once again rely on nBusMask for emulating A20 wrap-around
|
* a waste of time; however, if we decide to once again rely on nBusMask for emulating A20 wrap-around
|
||||||
* (instead of changing the physical memory map to alias the 2nd Mb to the 1st Mb), then performing
|
* (instead of changing the physical memory map to alias the 2nd Mb to the 1st Mb), then performing
|
||||||
* consistent masking will be important.
|
* consistent masking will be important.
|
||||||
|
|
@ -993,9 +993,9 @@ X86CPU.prototype.disablePageBlocks = function()
|
||||||
* It is recommended that you add an interrupt handler to the 8086 software that is to be run on the 80286,
|
* It is recommended that you add an interrupt handler to the 8086 software that is to be run on the 80286,
|
||||||
* which will treat these interrupts as invalid operations.
|
* which will treat these interrupts as invalid operations.
|
||||||
*
|
*
|
||||||
* This additional software does not significantly effect the existing 8086 software because the interrupts
|
* This additional software does not significantly effect [sic] the existing 8086 software because the interrupts
|
||||||
* do not normally occur and should not already have been used since they are in the interrupt group reserved
|
* do not normally occur and should not already have been used since they are in the interrupt group reserved
|
||||||
* by Intel. [Note to Intel: IBM caaaaaaan't hear you].
|
* by Intel. [NOTE: IBM ignored Intel's admonishments.]
|
||||||
*
|
*
|
||||||
* 2. Do not Rely on 8086/8088 Instruction Clock Counts
|
* 2. Do not Rely on 8086/8088 Instruction Clock Counts
|
||||||
*
|
*
|
||||||
|
|
@ -1035,7 +1035,7 @@ X86CPU.prototype.disablePageBlocks = function()
|
||||||
* 8. Do not Rely on the Value Written by PUSH SP
|
* 8. Do not Rely on the Value Written by PUSH SP
|
||||||
*
|
*
|
||||||
* The 80286 will push a different value on the stack for PUSH SP than the 8086/8088. If the value pushed is
|
* The 80286 will push a different value on the stack for PUSH SP than the 8086/8088. If the value pushed is
|
||||||
* important [and when would it NOT be???], replace PUSH SP instructions with the following three instructions:
|
* important [and when would it NOT be?], replace PUSH SP instructions with the following three instructions:
|
||||||
*
|
*
|
||||||
* PUSH BP
|
* PUSH BP
|
||||||
* MOV BP,SP
|
* MOV BP,SP
|
||||||
|
|
@ -1118,7 +1118,7 @@ X86CPU.prototype.initProcessor = function()
|
||||||
* Instruction handlers that contain "hard-coded" 80286 cycle times include: opINSb, opINSw, opOUTSb,
|
* Instruction handlers that contain "hard-coded" 80286 cycle times include: opINSb, opINSw, opOUTSb,
|
||||||
* opOUTSw, opENTER, and opLEAVE.
|
* opOUTSw, opENTER, and opLEAVE.
|
||||||
*/
|
*/
|
||||||
this.aOps = X86.aOps.slice(); // make copies of aOps and others before modifying them
|
this.aOps = X86.aOps.slice(); // make copies of opcode tables before modifying
|
||||||
this.aOpGrp4b = X86.aOpGrp4b.slice();
|
this.aOpGrp4b = X86.aOpGrp4b.slice();
|
||||||
this.aOpGrp4w = X86.aOpGrp4w.slice();
|
this.aOpGrp4w = X86.aOpGrp4w.slice();
|
||||||
this.nShiftCountMask = 0x1f; // on newer processors, all shift counts are MOD 32
|
this.nShiftCountMask = 0x1f; // on newer processors, all shift counts are MOD 32
|
||||||
|
|
@ -1326,8 +1326,8 @@ X86CPU.prototype.setReg = function(i, reg)
|
||||||
* Similarly, regLSP mirrors the linear address corresponding to SS:SP, and therefore you must rely on getSP()
|
* Similarly, regLSP mirrors the linear address corresponding to SS:SP, and therefore you must rely on getSP()
|
||||||
* to read the current SP, and setSP() and setSS() to update SP and SS.
|
* to read the current SP, and setSP() and setSS() to update SP and SS.
|
||||||
*
|
*
|
||||||
* The other segment registers, such as segDS and segES, have similar getters and setters, but they do not mirror
|
* The other segment registers, such as segDS and segES, have similar getters and setters, but we do not mirror
|
||||||
* any segment:offset values in the same way that regLIP mirrors CS:IP, or that regLSP mirrors SS:SP.
|
* any other segment:offset values in the same way that regLIP mirrors CS:IP, or that regLSP mirrors SS:SP.
|
||||||
*
|
*
|
||||||
* @this {X86CPU}
|
* @this {X86CPU}
|
||||||
*/
|
*/
|
||||||
|
|
@ -1366,7 +1366,7 @@ X86CPU.prototype.resetRegs = function()
|
||||||
*/
|
*/
|
||||||
this.regCR0 = X86.CR0.MSW.ON;
|
this.regCR0 = X86.CR0.MSW.ON;
|
||||||
this.addrIDT = 0; this.addrIDTLimit = 0x03FF;
|
this.addrIDT = 0; this.addrIDTLimit = 0x03FF;
|
||||||
this.regPS = this.nIOPL = 0; // these should be set before the first setPS() call
|
this.regPS = this.nIOPL = 0;// these should be set before the first setPS() call
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define all the result registers that can be used to "cache" arithmetic and logical flags.
|
* Define all the result registers that can be used to "cache" arithmetic and logical flags.
|
||||||
|
|
@ -1395,14 +1395,18 @@ X86CPU.prototype.resetRegs = function()
|
||||||
/*
|
/*
|
||||||
* These are used to snapshot regLIP and regLSP, to help make instructions restartable;
|
* These are used to snapshot regLIP and regLSP, to help make instructions restartable;
|
||||||
* currently opLIP is updated prior to every instruction, but opLSP is updated only for instructions
|
* currently opLIP is updated prior to every instruction, but opLSP is updated only for instructions
|
||||||
* that read/write the stack (eg, RETF) and should otherwise remain set to X86.ADDR_INVALID.
|
* that modify the stack pointer (eg, RETF) and should otherwise remain set to X86.ADDR_INVALID.
|
||||||
|
*
|
||||||
|
* More recently, opCS was added to selectively snapshot an instruction's original CS in case an
|
||||||
|
* exception occurs accessing the stack after a new CS has been loaded, allowing the exception handler
|
||||||
|
* to recover the old CS and make instructions like CALLF restartable; otherwise, opCS should remain -1.
|
||||||
*/
|
*/
|
||||||
this.opCS = -1;
|
this.opCS = -1;
|
||||||
this.opLIP = this.opLSP = X86.ADDR_INVALID;
|
this.opLIP = this.opLSP = X86.ADDR_INVALID;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Segment registers used to be defined as separate variables (eg, regCS and regCS0 stored the segment
|
* Segment registers used to be defined as separate selector and base variables (eg, regCS and regCS0),
|
||||||
* number and base linear address, respectively), but segment registers are now defined as X86Seg objects.
|
* but now they are defined as X86Seg objects.
|
||||||
*/
|
*/
|
||||||
this.segCS = new X86Seg(this, X86Seg.ID.CODE, "CS");
|
this.segCS = new X86Seg(this, X86Seg.ID.CODE, "CS");
|
||||||
this.segDS = new X86Seg(this, X86Seg.ID.DATA, "DS");
|
this.segDS = new X86Seg(this, X86Seg.ID.DATA, "DS");
|
||||||
|
|
@ -1455,8 +1459,8 @@ X86CPU.prototype.resetRegs = function()
|
||||||
* (and too difficult in protected-mode) to merit the overhead. Ditto for SP, which can't really
|
* (and too difficult in protected-mode) to merit the overhead. Ditto for SP, which can't really
|
||||||
* be considered a general-purpose register.
|
* be considered a general-purpose register.
|
||||||
*
|
*
|
||||||
* Every time getByte() is called, btMemLo is filled with the matching backtrack info; similarly,
|
* Every time getByte() is called, btiMem0 is filled with the matching backtrack info; similarly,
|
||||||
* every time getWord() is called, btMemLo and btMemHi are filled with the matching backtrack info
|
* every time getWord() is called, btiMem0 and btiMem1 are filled with the matching backtrack info
|
||||||
* for the low and high bytes, respectively.
|
* for the low and high bytes, respectively.
|
||||||
*/
|
*/
|
||||||
this.backTrack = {
|
this.backTrack = {
|
||||||
|
|
|
||||||
|
|
@ -49,12 +49,15 @@ X86.opADDmb = function ADDmb()
|
||||||
var b = this.getIPByte();
|
var b = this.getIPByte();
|
||||||
/*
|
/*
|
||||||
* Opcode bytes 0x00 0x00 are sufficiently uncommon that it's more likely we've started
|
* Opcode bytes 0x00 0x00 are sufficiently uncommon that it's more likely we've started
|
||||||
* executing in the weeds, so we'll print a warning if you're in DEBUG mode, and optionally
|
* executing in the weeds, so if you're in DEBUG mode, we'll print a warning and stop the
|
||||||
* stop the CPU if a Debugger is available.
|
* CPU if a Debugger is available.
|
||||||
|
*
|
||||||
|
* Notice that we also test fRunning: this allows the Debugger to step over the instruction,
|
||||||
|
* because its trace ("t") command doesn't "run" the CPU; it merely "steps" the CPU.
|
||||||
*/
|
*/
|
||||||
if (DEBUG && !b) {
|
if (DEBUG && !b && this.aFlags.fRunning) {
|
||||||
this.printMessage("suspicious opcode: 0x00 0x00", DEBUGGER || this.bitsMessage);
|
this.printMessage("suspicious opcode: 0x00 0x00", DEBUGGER || this.bitsMessage);
|
||||||
if (DEBUGGER && this.dbg) this.stopCPU();
|
if (DEBUGGER && this.dbg) this.dbg.stopCPU();
|
||||||
}
|
}
|
||||||
this.aOpModMemByte[b].call(this, X86.fnADDb);
|
this.aOpModMemByte[b].call(this, X86.fnADDb);
|
||||||
};
|
};
|
||||||
|
|
@ -4157,7 +4160,7 @@ X86.opHLT = function HLT()
|
||||||
*/
|
*/
|
||||||
if (DEBUGGER && this.dbg && this.messageEnabled(Messages.HALT)) {
|
if (DEBUGGER && this.dbg && this.messageEnabled(Messages.HALT)) {
|
||||||
this.rewindIP(-1); // this is purely for the Debugger's benefit, to show the HLT
|
this.rewindIP(-1); // this is purely for the Debugger's benefit, to show the HLT
|
||||||
this.stopCPU();
|
this.dbg.stopCPU();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue