v1.19.7: Windows 95 boots to the desktop

This commit is contained in:
Jeff Parsons 2015-09-21 18:37:44 -07:00
commit a774fb983e
33 changed files with 8372 additions and 1411 deletions

View file

@ -162,7 +162,7 @@ function Debugger(parmsDbg)
* nSegment
* sel
* off
* addr (physical address, if any; eg, if symbols are for a ROM)
* addr (physical address, if any; eg, symbols for a ROM)
* len
* aSymbols
* aOffsets
@ -856,8 +856,8 @@ if (DEBUGGER) {
/* 0x96 */ [Debugger.INS.XCHG, Debugger.TYPE_AX | Debugger.TYPE_BOTH, Debugger.TYPE_SI | Debugger.TYPE_BOTH],
/* 0x97 */ [Debugger.INS.XCHG, Debugger.TYPE_AX | Debugger.TYPE_BOTH, Debugger.TYPE_DI | Debugger.TYPE_BOTH],
/* 0x98 */ [Debugger.INS.CBW],
/* 0x99 */ [Debugger.INS.CWD],
/* 0x98 */ [Debugger.INS.CBW], // TODO: CWDE [sign-extend AX into EAX (instead of AL into AX) when operand size is 32 bits]
/* 0x99 */ [Debugger.INS.CWD], // TODO: CDQ [sign-extend EAX into EDX:EAX (instead of AX into DX:AX) when operand size is 32 bits]
/* 0x9A */ [Debugger.INS.CALL, Debugger.TYPE_IMM | Debugger.TYPE_FARP | Debugger.TYPE_IN],
/* 0x9B */ [Debugger.INS.WAIT],
/* 0x9C */ [Debugger.INS.PUSHF],
@ -1272,6 +1272,7 @@ if (DEBUGGER) {
if (Interrupts.WINDBG.ENABLED || Interrupts.WINDBGRM.ENABLED) {
this.fWinDbg = null;
this.cTrapFaults = 0;
this.fIgnoreNextCheckFault = false;
this.cpu.addIntNotify(Interrupts.WINCB.VECTOR, this.intWindowsCallBack.bind(this));
this.cpu.addIntNotify(Interrupts.WINDBG.VECTOR, this.intWindowsDebugger.bind(this));
@ -1493,10 +1494,13 @@ if (DEBUGGER) {
return function onInt41Return(nLevel) {
if ((cpu.regEAX & 0xffff) != Interrupts.WINDBG.LOADED) {
cpu.regEAX = (cpu.regEAX & ~0xffff) | Interrupts.WINDBG.LOADED;
dbg.println("INT 0x41 handling enabled");
/*
* TODO: We need a DEBUGGER message category; using the MEM category for now.
*/
dbg.printMessage("INT 0x41 handling enabled", Messages.MEM);
dbg.fWinDbg = true;
} else {
dbg.println("INT 0x41 monitoring enabled");
dbg.printMessage("INT 0x41 monitoring enabled", Messages.MEM);
dbg.fWinDbg = false;
}
};
@ -1513,7 +1517,7 @@ if (DEBUGGER) {
case Interrupts.WINDBG.IS_LOADED: // 0x004F
if (this.fWinDbg) {
cpu.regEAX = (cpu.regEAX & ~0xffff) | Interrupts.WINDBG.LOADED;
this.println("INT 0x41 handling enabled");
this.printMessage("INT 0x41 handling enabled", Messages.MEM);
}
break;
@ -1583,8 +1587,16 @@ if (DEBUGGER) {
*/
if (this.fWinDbg) {
dbgAddr = this.newAddr(cpu.regEDX, CX);
this.println("INT 0x41 TRAPFAULT: fault=" + str.toHexWord(BX) + " error=" + str.toHexLong(cpu.regESI) + " addr=" + this.toHexAddr(dbgAddr));
this.addBreakpoint(this.aBreakExec, dbgAddr, true);
if (!this.cTrapFaults++) {
this.println("INT 0x41 TRAPFAULT: fault=" + str.toHexWord(BX) + " error=" + str.toHexLong(cpu.regESI) + " addr=" + this.toHexAddr(dbgAddr));
this.addBreakpoint(this.aBreakExec, dbgAddr, true);
this.historyInit(true); // temporary breakpoints don't normally trigger history, but in this case, we want it to
} else {
this.println("TRAPFAULT failed");
this.findBreakpoint(this.aBreakExec, dbgAddr, true, true, true);
this.cTrapFaults = 0;
this.stopCPU();
}
}
break;
@ -1675,14 +1687,14 @@ if (DEBUGGER) {
return function onInt68Return(nLevel) {
if ((cpu.regEAX & 0xffff) != Interrupts.WINDBGRM.LOADED) {
cpu.regEAX = (cpu.regEAX & ~0xffff) | Interrupts.WINDBGRM.LOADED;
dbg.println("INT 0x68 handling enabled");
dbg.printMessage("INT 0x68 handling enabled", Messages.MEM);
/*
* If we turn on INT 0x68 handling, we must also turn on INT 0x41 handling,
* because Windows assumes that the latter handler exists whenever the former does.
*/
dbg.fWinDbg = dbg.fWinDbgRM = true;
} else {
dbg.println("INT 0x68 monitoring enabled");
dbg.printMessage("INT 0x68 monitoring enabled", Messages.MEM);
dbg.fWinDbgRM = false;
}
};
@ -3608,7 +3620,7 @@ if (DEBUGGER) {
};
/**
* historyInit()
* historyInit(fQuiet)
*
* This function is intended to be called by the constructor, reset(), addBreakpoint(), findBreakpoint()
* and any other function that changes the checksEnabled() criteria used to decide whether checkInstruction()
@ -3618,12 +3630,15 @@ if (DEBUGGER) {
* and if the arrays are no longer needed, then deallocate them.
*
* @this {Debugger}
* @param {boolean} [fQuiet]
*/
Debugger.prototype.historyInit = function()
Debugger.prototype.historyInit = function(fQuiet)
{
var i;
if (!this.checksEnabled()) {
if (this.aOpcodeHistory && this.aOpcodeHistory.length) this.println("instruction history buffer freed");
if (this.aOpcodeHistory && this.aOpcodeHistory.length && !fQuiet) {
this.println("instruction history buffer freed");
}
this.iOpcodeHistory = 0;
this.aOpcodeHistory = [];
this.aaOpcodeCounts = [];
@ -3639,7 +3654,9 @@ if (DEBUGGER) {
this.aOpcodeHistory[i] = this.newAddr();
}
this.iOpcodeHistory = 0;
this.println("instruction history buffer allocated");
if (!fQuiet) {
this.println("instruction history buffer allocated");
}
}
if (!this.aaOpcodeCounts || !this.aaOpcodeCounts.length) {
this.aaOpcodeCounts = new Array(256);
@ -4272,14 +4289,20 @@ if (DEBUGGER) {
if (!fTempBreak || dbgAddrBreak.fTempBreak) {
fFound = true;
if (fRemove) {
if (!dbgAddrBreak.fTempBreak) {
if (!fQuiet) this.printBreakpoint(aBreak, i, "cleared");
if (!dbgAddrBreak.fTempBreak && !fQuiet) {
this.printBreakpoint(aBreak, i, "cleared");
}
aBreak.splice(i, 1);
if (aBreak != this.aBreakExec) {
this.cpu.removeMemBreak(addr, aBreak == this.aBreakWrite, dbgAddrBreak.type != Debugger.ADDRTYPE.PHYSICAL);
}
this.historyInit();
/*
* We'll mirror the logic in addBreakpoint() and leave the history buffer alone if this
* was a temporary breakpoint.
*/
if (!dbgAddrBreak.fTempBreak) {
this.historyInit();
}
break;
}
if (!fQuiet) this.printBreakpoint(aBreak, i, "exists");

View file

@ -510,6 +510,17 @@ Memory.prototype = {
this.bitPTEDirty = blockPhys? Memory.adjustEndian(X86.PTE.ACCESSED | X86.PTE.DIRTY) : 0;
this.bitPTEAccessed = blockPhys? Memory.adjustEndian(X86.PTE.ACCESSED) : 0;
},
/**
* printAddr(sMessage)
*
* @this {Memory}
* @param {string} sMessage
*/
printAddr: function(sMessage) {
if (DEBUG && this.dbg && this.dbg.messageEnabled(Messages.MEM)) {
this.dbg.printMessage(sMessage + ' ' + (this.addr != null? ('%' + str.toHex(this.addr)) : '#' + this.id), true);
}
},
/**
* addBreakpoint(off, fWrite, cpu)
*
@ -528,18 +539,14 @@ Memory.prototype = {
if (cpu) this.cpu = cpu;
this.setReadAccess(Memory.afnChecked, false);
}
if (DEBUG && this.dbg && this.dbg.messageEnabled(Messages.MEM)) {
this.dbg.printMessage("read breakpoint added to memory block " + str.toHex(this.addr), true);
}
if (DEBUG) this.printAddr("read breakpoint added to memory block");
}
else {
if (this.cWriteBreakpoints++ === 0) {
if (cpu) this.cpu = cpu;
this.setWriteAccess(Memory.afnChecked, false);
}
if (DEBUG && this.dbg && this.dbg.messageEnabled(Messages.MEM)) {
this.dbg.printMessage("write breakpoint added to memory block " + str.toHex(this.addr), true);
}
if (DEBUG) this.printAddr("write breakpoint added to memory block");
}
},
/**
@ -562,18 +569,14 @@ Memory.prototype = {
if (!fWrite) {
if (--this.cReadBreakpoints === 0) {
this.resetReadAccess();
if (DEBUG && this.dbg && this.dbg.messageEnabled(Messages.MEM)) {
this.dbg.printMessage("all read breakpoints removed from memory block " + str.toHex(this.addr), true);
}
if (DEBUG) this.printAddr("all read breakpoints removed from memory block");
}
Component.assert(this.cReadBreakpoints >= 0);
}
else {
if (--this.cWriteBreakpoints === 0) {
this.resetWriteAccess();
if (DEBUG && this.dbg && this.dbg.messageEnabled(Messages.MEM)) {
this.dbg.printMessage("all write breakpoints removed from memory block " + str.toHex(this.addr), true);
}
if (DEBUG) this.printAddr("all write breakpoints removed from memory block");
}
Component.assert(this.cWriteBreakpoints >= 0);
}

View file

@ -3980,7 +3980,7 @@ X86CPU.prototype.getIPWord = function()
* getIPDisp()
*
* @this {X86CPU}
* @return {number} sign-extended value from the byte at the current IP; IP advanced by 1
* @return {number} sign-extended (32-bit) value from the byte at the current IP; IP advanced by 1
*/
X86CPU.prototype.getIPDisp = function()
{

File diff suppressed because it is too large Load diff

View file

@ -2056,6 +2056,10 @@ X86.opGRP1w = function GRP1w()
/**
* op=0x83 (GRP1 word,disp)
*
* WARNING: This passes getIPDisp() as the fnSrc parameter, which returns a 32-bit signed value,
* so the worker functions (ie, the functions listed in aOpGrp1w[]) MUST mask their result with maskData,
* to avoid setting bits beyond the current operand size.
*
* @this {X86CPU}
*/
X86.opGRP1sw = function GRP1sw()