v1.19.5 update (fixes a CALLF bug and a VGA ATC bug, and adds improved WDEB386-style load notifications)

This commit is contained in:
Jeff Parsons 2015-09-12 02:05:05 -07:00
commit b00b524e01
8 changed files with 1349 additions and 1267 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1275,6 +1275,7 @@ if (DEBUGGER) {
if (Interrupts.WINDBG.ENABLED || Interrupts.WINDBGRM.ENABLED) {
this.fWinDbg = null;
this.cpu.addIntNotify(Interrupts.WINCB.VECTOR, this.intWindowsCallBack.bind(this));
this.cpu.addIntNotify(Interrupts.WINDBG.VECTOR, this.intWindowsDebugger.bind(this));
}
if (Interrupts.WINDBGRM.ENABLED) {
@ -1336,13 +1337,13 @@ if (DEBUGGER) {
var len = this.getLong(dbgAddr, 4);
var dbgAddrDevice = this.newAddr(this.getLong(dbgAddr, 4), this.getShort(dbgAddr, 2));
var dbgAddrModule = this.newAddr(this.getLong(dbgAddr, 4), this.getShort(dbgAddr, 2));
sel = this.getShort(dbgAddr, 2) || sel;
// sel = this.getShort(dbgAddr, 2) || sel;
var sModule = this.getSZ(dbgAddrModule).toUpperCase();
var sDevice = this.getSZ(dbgAddrDevice).toUpperCase();
var sSection = (fCode? "_CODE" : "_DATA") + str.toHex(nSeg, 2);
if (fPrint) {
/*
* Mimic WDEB386 output
* Mimics WDEB386 output, except that WDEB386 only displays a linear address, omitting the selector.
*/
this.println(sModule + '!' + sDevice + "!undefined " + (fCode? "code" : "data") + '(' + str.toHex(nSeg, 4) + ")=" + str.toHex(sel, 4) + ':' + str.toHex(off) + " len " + str.toHex(len));
}
@ -1351,6 +1352,55 @@ if (DEBUGGER) {
this.addSymbols(sel, off, len, aSymbols);
};
/**
* intWindowsCallBack()
*
* This intercepts calls to Windows callback addresses, which use INT 0x30 (aka Transfer Space Fault).
*
* We're only interested in one particular callback: the one specifying VW32_Int41Dispatch (0x002A002A)
* in EAX.
*
* At the time that INT 0x30 occurs, a far 32-bit call has been made, preceded by a near 32-bit call,
* preceded by a 32-bit push of the Windows Debugger function # that would normally be in EAX if this had
* been an actual INT 0x41.
*
* NOTE: Regardless whether we're "handling" INT 0x41 or merely "monitoring" INT 0x41, as far as THIS
* interrupt is concerned, we always let the system process it, because execution never continues at the
* instruction following an INT 0x30; in fact, execution doesn't even continue after the far 32-bit call
* (even though the kernel places a "RET 4" after that call). So, rather than recreate all that automatic
* address popping, we let the system do it for us, since it's designed to work whether a debugger (eg,
* WDEB386's Debug VXD) is installed or not.
*
* @this {Debugger}
* @param {number} addr
* @return {boolean} true to proceed with the INT 0x30 software interrupt
*/
Debugger.prototype.intWindowsCallBack = function(addr)
{
var cpu = this.cpu;
if (this.fWinDbg != null && cpu.regEAX == 0x002A002A) {
var DX = cpu.regEDX & 0xffff;
var SI = cpu.regESI & 0xffff;
var dbgAddr = this.newAddr(cpu.getSP() + 0x0C, cpu.getSS());
var EAX = this.getLong(dbgAddr);
switch(EAX) {
case Interrupts.WINDBG.LOAD_SEG32:
/*
* SI == segment type:
* 0x0 code selector
* 0x1 data selector
* DX:EBX -> D386_Device_Params structure (see addSectionInfo() for details)
*/
this.addSectionInfo(this.newAddr(cpu.regEBX, DX), !SI, this.fWinDbg);
break;
}
}
return true;
};
/**
* intWindowsDebugger()
*
@ -1430,7 +1480,7 @@ if (DEBUGGER) {
break;
default:
if (this.fWinDbg) {
if (MAXDEBUG && this.fWinDbg) {
this.println("INT 0x41: " + str.toHexWord(AX));
}
break;
@ -1561,7 +1611,7 @@ if (DEBUGGER) {
break;
default:
if (this.fWinDbgRM) {
if (MAXDEBUG && this.fWinDbgRM) {
this.println("INT 0x68: " + str.toHexByte(AH));
}
break;
@ -1616,7 +1666,7 @@ if (DEBUGGER) {
{
var cpu = this.cpu;
var AL = cpu.regEAX & 0xff;
this.println("INT 0x68 callback: " + str.toHexByte(AL));
if (MAXDEBUG) this.println("INT 0x68 callback: " + str.toHexByte(AL));
if (AL == 5) {
cpu.regECX = cpu.regESI = 0; // our in-machine debugger footprint is zero
cpu.regEAX = (cpu.regEAX & ~0xff) | 0x01;

View file

@ -61,6 +61,9 @@ var Interrupts = {
MOUSE: 0x33,
ALT_DISK: 0x40, // HDC BIOS saves original FDC BIOS vector here
ALT_VIDEO: 0x6D, // IBM VGA BIOS saves original video BIOS vector here
WINCB: {
VECTOR: 0x30 // Windows PM call-back interface (aka Transfer Space Fault)
},
WINDBG: { // Windows Debugger protected-mode interface
VECTOR: 0x41, // (AX==command)
IS_LOADED: 0x004F, // DS_DebLoaded

View file

@ -2461,6 +2461,7 @@ Card.prototype.dumpVideoCard = function()
this.dumpRegs(" GRC", this.regGRCIndx, this.regGRCData, this.asGRCRegs);
this.dumpRegs(" SEQ", this.regSEQIndx, this.regSEQData, this.asSEQRegs);
this.dumpRegs(" ATC", this.regATCIndx, this.regATCData, this.asATCRegs);
this.dumpRegs(" ATCINDX", this.regATCIndx);
this.dbg.println(" ATCDATA: " + this.fATCData);
this.dumpRegs(" FEAT", this.regFeat);
this.dumpRegs(" MISC", this.regMisc);
@ -5894,20 +5895,44 @@ Video.prototype.outFeat = function(port, bOut, addrFrom)
};
/**
* inATC(port, addrFrom)
* inATCIndx(port, addrFrom)
*
* Technically, port 0x3C0 is readable only on a VGA, but we allow reads on an EGA as well,
* primarily for debugging purposes. Moreover, ATC port reads do NOT toggle the ATC address/data
* flip-flop; only writes have that effect.
*
* @this {Video}
* @param {number} port (0x3C0)
* @param {number} [addrFrom] (not defined whenever the Debugger tries to read the specified port)
* @return {number}
*/
Video.prototype.inATC = function(port, addrFrom)
Video.prototype.inATCIndx = function(port, addrFrom)
{
var b = this.cardEGA.fATCData? this.cardEGA.regATCData[this.cardEGA.regATCIndx & Card.ATC.INDX_MASK] : this.cardEGA.regATCIndx;
var b = this.cardEGA.regATCIndx;
if (!addrFrom || this.messageEnabled()) {
this.printMessageIO(Card.ATC.PORT, null, addrFrom, "ATC." + (this.cardEGA.fATCData? this.cardEGA.asATCRegs[this.cardEGA.regATCIndx & Card.ATC.INDX_MASK] : "INDX"), b);
this.printMessageIO(Card.ATC.PORT, null, addrFrom, "ATC.INDX", b);
}
return b;
};
/**
* inATCData(port, addrFrom)
*
* Technically, port 0x3C0 is readable only on a VGA, but we allow reads on an EGA as well,
* primarily for debugging purposes. Moreover, ATC port reads do NOT toggle the ATC address/data
* flip-flop; only writes have that effect.
*
* @this {Video}
* @param {number} port (0x3C1)
* @param {number} [addrFrom] (not defined whenever the Debugger tries to read the specified port)
* @return {number}
*/
Video.prototype.inATCData = function(port, addrFrom)
{
var b = this.cardEGA.regATCData[this.cardEGA.regATCIndx & Card.ATC.INDX_MASK];
if (!addrFrom || this.messageEnabled()) {
this.printMessageIO(Card.ATC.PORT, null, addrFrom, "ATC." + this.cardEGA.asATCRegs[this.cardEGA.regATCIndx & Card.ATC.INDX_MASK], b);
}
this.cardEGA.fATCData = !this.cardEGA.fATCData;
return b;
};
@ -6880,8 +6905,8 @@ Video.aCGAPortOutput = {
};
Video.aEGAPortInput = {
0x3C0: Video.prototype.inATC, // technically, only readable on a VGA, but I want the Debugger to be able to read this, too
0x3C1: Video.prototype.inATC, // technically, only readable on a VGA, but I want the Debugger to be able to read this, too
0x3C0: Video.prototype.inATCIndx, // technically, only readable on a VGA, but I want the Debugger to be able to read this, too
0x3C1: Video.prototype.inATCData, // technically, only readable on a VGA, but I want the Debugger to be able to read this, too
0x3C2: Video.prototype.inStatus0,
0x3C4: Video.prototype.inSEQIndx, // technically, only readable on a VGA, but I want the Debugger to be able to read this, too
0x3C5: Video.prototype.inSEQData, // technically, only readable on a VGA, but I want the Debugger to be able to read this, too
@ -6892,7 +6917,7 @@ Video.aEGAPortInput = {
/*
* WARNING: Unlike the EGA, a standard VGA does not support writes to 0x3C1, but it's easier for me to leave that
* ability in place, treating the VGA as a superset of the EGA as much as possible; will any code break because word
* I/O to port 0x3C0 actually works? Possibly, but highly unlikely.
* OUTs to port 0x3C0 (and/or byte OUTs to port 0x3C1) actually work? Possibly, but highly unlikely.
*/
Video.aEGAPortOutput = {
0x3BA: Video.prototype.outFeat,

View file

@ -562,7 +562,7 @@ X86.fnCALLF = function CALLF(off, sel)
{
var oldCS = this.getCS();
var oldIP = this.getIP();
var oldSize = this.segCS.sizeData;
var oldSize = (I386? this.sizeData : 2);
if (this.setCSIP(off, sel, true) != null) {
this.pushData(oldCS, oldSize);
this.pushData(oldIP, oldSize);
@ -1415,6 +1415,10 @@ X86.fnINT = function INT(nIDT, nError, nCycles)
var oldIP = this.getIP();
var addr = this.segCS.loadIDT(nIDT);
if (addr !== X86.ADDR_INVALID) {
/*
* TODO: Harmonize this with the code in fnCALLF(), which relies on the OPERAND size in
* effect at the time of the call, NOT the size of the new segCS.
*/
var size = this.segCS.sizeFrame;
this.pushData(oldPS, size);
this.pushData(oldCS, size);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long