Starting on 1.16.1

This commit is contained in:
Jeff Parsons 2014-11-29 08:29:25 -08:00 committed by jeffpar
commit 6248972684
121 changed files with 1261 additions and 1091 deletions

View file

@ -1327,13 +1327,19 @@ ChipSet.prototype.getRTCCycleLimit = function(nCycles)
var nCyclesUpdate = this.nRTCCyclesNextUpdate - this.cpu.getCycles(this.fScaleTimers);
if (nCyclesUpdate > 0) {
if (nCycles > nCyclesUpdate) {
if (DEBUG) this.messageDebugger("getRTCCycleLimit(" + nCycles + "): reduced to " + nCyclesUpdate + " cycles", Debugger.MESSAGE.RTC);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.RTC)) {
this.messageDebugger("getRTCCycleLimit(" + nCycles + "): reduced to " + nCyclesUpdate + " cycles", Debugger.MESSAGE.RTC);
}
nCycles = nCyclesUpdate;
} else {
if (DEBUG) this.messageDebugger("getRTCCycleLimit(" + nCycles + "): already less than " + nCyclesUpdate + " cycles", Debugger.MESSAGE.RTC);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.RTC)) {
this.messageDebugger("getRTCCycleLimit(" + nCycles + "): already less than " + nCyclesUpdate + " cycles", Debugger.MESSAGE.RTC);
}
}
} else {
if (DEBUG) this.messageDebugger("RTC next update has passed by " + nCyclesUpdate + " cycles", Debugger.MESSAGE.RTC);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.RTC)) {
this.messageDebugger("RTC next update has passed by " + nCyclesUpdate + " cycles", Debugger.MESSAGE.RTC);
}
}
}
return nCycles;
@ -2278,7 +2284,9 @@ ChipSet.prototype.inDMAChannelAddr = function(iDMAC, iChannel, port, addrFrom)
var controller = this.aDMACs[iDMAC];
var channel = controller.aChannels[iChannel];
var b = channel.addrCurrent[controller.bIndex];
this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".ADDR[" + controller.bIndex + "]", Debugger.MESSAGE.DMA, b);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".ADDR[" + controller.bIndex + "]", Debugger.MESSAGE.DMA, b);
}
controller.bIndex ^= 0x1;
/*
* Technically, aTimers[ChipSet.TIMER1.INDEX].fOut is what drives DMA requests for DMA channel 0 (ChipSet.DMA_REFRESH),
@ -2313,7 +2321,9 @@ ChipSet.prototype.inDMAChannelAddr = function(iDMAC, iChannel, port, addrFrom)
ChipSet.prototype.outDMAChannelAddr = function outDMAChannelAddr(iDMAC, iChannel, port, bOut, addrFrom)
{
var controller = this.aDMACs[iDMAC];
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".ADDR[" + controller.bIndex + "]", Debugger.MESSAGE.DMA);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".ADDR[" + controller.bIndex + "]", Debugger.MESSAGE.DMA);
}
var channel = controller.aChannels[iChannel];
channel.addrCurrent[controller.bIndex] = channel.addrInit[controller.bIndex] = bOut;
controller.bIndex ^= 0x1;
@ -2334,7 +2344,9 @@ ChipSet.prototype.inDMAChannelCount = function(iDMAC, iChannel, port, addrFrom)
var controller = this.aDMACs[iDMAC];
var channel = controller.aChannels[iChannel];
var b = channel.countCurrent[controller.bIndex];
this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".COUNT[" + controller.bIndex + "]", Debugger.MESSAGE.DMA, b);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".COUNT[" + controller.bIndex + "]", Debugger.MESSAGE.DMA, b);
}
controller.bIndex ^= 0x1;
/*
* Technically, aTimers[ChipSet.TIMER1.INDEX].fOut is what drives DMA requests for DMA channel 0 (ChipSet.DMA_REFRESH),
@ -2373,7 +2385,9 @@ ChipSet.prototype.inDMAChannelCount = function(iDMAC, iChannel, port, addrFrom)
ChipSet.prototype.outDMAChannelCount = function(iDMAC, iChannel, port, bOut, addrFrom)
{
var controller = this.aDMACs[iDMAC];
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".COUNT[" + controller.bIndex + "]", Debugger.MESSAGE.DMA);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".COUNT[" + controller.bIndex + "]", Debugger.MESSAGE.DMA);
}
var channel = controller.aChannels[iChannel];
channel.countCurrent[controller.bIndex] = channel.countInit[controller.bIndex] = bOut;
controller.bIndex ^= 0x1;
@ -2414,7 +2428,9 @@ ChipSet.prototype.inDMAStatus = function(iDMAC, port, addrFrom)
var controller = this.aDMACs[iDMAC];
var b = controller.bStatus | ChipSet.DMA_STATUS.CH0_TC;
controller.bStatus &= ~ChipSet.DMA_STATUS.ALL_TC;
this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".STATUS", Debugger.MESSAGE.DMA, b);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".STATUS", Debugger.MESSAGE.DMA, b);
}
return b;
};
@ -2429,7 +2445,9 @@ ChipSet.prototype.inDMAStatus = function(iDMAC, port, addrFrom)
*/
ChipSet.prototype.outDMACmd = function(iDMAC, port, bOut, addrFrom)
{
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CMD", Debugger.MESSAGE.DMA);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CMD", Debugger.MESSAGE.DMA);
}
this.aDMACs[iDMAC].bCmd = bOut;
};
@ -2455,7 +2473,9 @@ ChipSet.prototype.outDMACmd = function(iDMAC, port, bOut, addrFrom)
ChipSet.prototype.outDMAReq = function(iDMAC, port, bOut, addrFrom)
{
var controller = this.aDMACs[iDMAC];
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".REQ", Debugger.MESSAGE.DMA);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".REQ", Debugger.MESSAGE.DMA);
}
/*
* Bits 0-1 contain the channel number
*/
@ -2480,7 +2500,9 @@ ChipSet.prototype.outDMAReq = function(iDMAC, port, bOut, addrFrom)
ChipSet.prototype.outDMAMask = function(iDMAC, port, bOut, addrFrom)
{
var controller = this.aDMACs[iDMAC];
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".MASK", Debugger.MESSAGE.DMA);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".MASK", Debugger.MESSAGE.DMA);
}
var iChannel = bOut & ChipSet.DMA_MASK.CHANNEL;
var channel = controller.aChannels[iChannel];
channel.masked = !!(bOut & ChipSet.DMA_MASK.CHANNEL_SET);
@ -2498,7 +2520,9 @@ ChipSet.prototype.outDMAMask = function(iDMAC, port, bOut, addrFrom)
*/
ChipSet.prototype.outDMAMode = function(iDMAC, port, bOut, addrFrom)
{
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".MODE", Debugger.MESSAGE.DMA);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".MODE", Debugger.MESSAGE.DMA);
}
var iChannel = bOut & ChipSet.DMA_MODE.CHANNEL;
this.aDMACs[iDMAC].aChannels[iChannel].mode = bOut;
};
@ -2517,7 +2541,9 @@ ChipSet.prototype.outDMAMode = function(iDMAC, port, bOut, addrFrom)
*/
ChipSet.prototype.outDMAResetFF = function(iDMAC, port, bOut, addrFrom)
{
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".RESET_FF", Debugger.MESSAGE.DMA);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".RESET_FF", Debugger.MESSAGE.DMA);
}
this.aDMACs[iDMAC].bIndex = 0;
};
@ -2532,7 +2558,9 @@ ChipSet.prototype.outDMAResetFF = function(iDMAC, port, bOut, addrFrom)
*/
ChipSet.prototype.outDMAMasterClear = function(iDMAC, port, bOut, addrFrom)
{
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".MASTER_CLEAR", Debugger.MESSAGE.DMA);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".MASTER_CLEAR", Debugger.MESSAGE.DMA);
}
/*
* The value written to this port doesn't matter; any write triggers a "master clear" operation
*
@ -2557,7 +2585,9 @@ ChipSet.prototype.outDMAMasterClear = function(iDMAC, port, bOut, addrFrom)
ChipSet.prototype.inDMAPageReg = function(iDMAC, iChannel, port, addrFrom)
{
var bIn = this.aDMACs[iDMAC].aChannels[iChannel].bPage;
this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".PAGE", Debugger.MESSAGE.DMA, bIn);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".PAGE", Debugger.MESSAGE.DMA, bIn);
}
return bIn;
};
@ -2573,7 +2603,9 @@ ChipSet.prototype.inDMAPageReg = function(iDMAC, iChannel, port, addrFrom)
*/
ChipSet.prototype.outDMAPageReg = function(iDMAC, iChannel, port, bOut, addrFrom)
{
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".PAGE", Debugger.MESSAGE.DMA);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".PAGE", Debugger.MESSAGE.DMA);
}
this.aDMACs[iDMAC].aChannels[iChannel].bPage = bOut;
};
@ -2589,7 +2621,9 @@ ChipSet.prototype.outDMAPageReg = function(iDMAC, iChannel, port, bOut, addrFrom
ChipSet.prototype.inDMAPageSpare = function(iSpare, port, addrFrom)
{
var bIn = this.abDMAPageSpare[iSpare];
this.messagePort(port, null, addrFrom, "DMA.SPARE" + iSpare + ".PAGE", Debugger.MESSAGE.DMA, bIn);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, null, addrFrom, "DMA.SPARE" + iSpare + ".PAGE", Debugger.MESSAGE.DMA, bIn);
}
return bIn;
};
@ -2604,7 +2638,9 @@ ChipSet.prototype.inDMAPageSpare = function(iSpare, port, addrFrom)
*/
ChipSet.prototype.outDMAPageSpare = function(iSpare, port, bOut, addrFrom)
{
this.messagePort(port, bOut, addrFrom, "DMA.SPARE" + iSpare + ".PAGE", Debugger.MESSAGE.DMA);
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA.SPARE" + iSpare + ".PAGE", Debugger.MESSAGE.DMA);
}
this.abDMAPageSpare[iSpare] = bOut;
};
@ -2672,7 +2708,9 @@ ChipSet.prototype.requestDMA = function(iDMAChannel, done)
var channel = controller.aChannels[iChannel];
if (!channel.component || !channel.fnTransfer || !channel.obj) {
if (DEBUG) this.messageDebugger("requestDMA(" + iDMAChannel + "): not connected to a component", Debugger.MESSAGE.DMA);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.OTHER)) {
this.messageDebugger("requestDMA(" + iDMAChannel + "): not connected to a component", Debugger.MESSAGE.DMA | Debugger.MESSAGE.OTHER);
}
if (done) done(true);
return;
}
@ -2687,7 +2725,9 @@ ChipSet.prototype.requestDMA = function(iDMAChannel, done)
if (done) channel.done = done;
if (channel.masked) {
if (DEBUG) this.messageDebugger("requestDMA(" + iDMAChannel + "): channel masked, request queued", Debugger.MESSAGE.DMA);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.OTHER)) {
this.messageDebugger("requestDMA(" + iDMAChannel + "): channel masked, request queued", Debugger.MESSAGE.DMA | Debugger.MESSAGE.OTHER);
}
return;
}
@ -2738,7 +2778,7 @@ ChipSet.prototype.advanceDMA = function(channel, fInit)
var addr = (channel.bPage << 16) | (channel.addrCurrent[1] << 8) | channel.addrCurrent[0];
if (DEBUG && DEBUGGER && channel.sAddrDebug === null) {
channel.sAddrDebug = str.toHex(addr >> 4, 4) + ":" + str.toHex(addr & 0xf, 4);
if (this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.DMA | (iDMAChannel == ChipSet.DMA_FDC? Debugger.MESSAGE.FDC : (iDMAChannel == ChipSet.DMA_HDC? Debugger.MESSAGE.HDC : 0))) && channel.xfer != ChipSet.DMA_MODE.XFER_WRITE) {
if (this.messageEnabled(Debugger.MESSAGE.DMA | (iDMAChannel == ChipSet.DMA_FDC? Debugger.MESSAGE.FDC : (iDMAChannel == ChipSet.DMA_HDC? Debugger.MESSAGE.HDC : 0))) && channel.xfer != ChipSet.DMA_MODE.XFER_WRITE) {
this.dbg.message("advanceDMA(" + iDMAChannel + ") transferring " + channel.cbDebug + " bytes from " + channel.sAddrDebug);
this.dbg.doDump("db", channel.sAddrDebug, "l" + Math.floor((channel.cbDebug + 15) / 16));
}
@ -2749,7 +2789,9 @@ ChipSet.prototype.advanceDMA = function(channel, fInit)
channel.fnTransfer.call(channel.component, channel.obj, -1, function onTransferDMA(b, fAsync) {
if (b < 0) {
if (!channel.fWarning) {
if (DEBUG) obj.messageDebugger("advanceDMA(" + iDMAChannel + ") ran out of data, assuming 0xff", Debugger.MESSAGE.DMA);
if (DEBUG && obj.messageEnabled(Debugger.MESSAGE.DMA)) {
obj.messageDebugger("advanceDMA(" + iDMAChannel + ") ran out of data, assuming 0xff", Debugger.MESSAGE.DMA);
}
channel.fWarning = true;
}
/*
@ -2796,7 +2838,9 @@ ChipSet.prototype.advanceDMA = function(channel, fInit)
}
}
else {
if (DEBUG) this.messageDebugger("advanceDMA(" + iDMAChannel + ") unsupported xfer mode: " + str.toHexWord(channel.xfer), Debugger.MESSAGE.DMA | Debugger.MESSAGE.WARN);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.WARN)) {
this.messageDebugger("advanceDMA(" + iDMAChannel + ") unsupported xfer mode: " + str.toHexWord(channel.xfer), Debugger.MESSAGE.DMA | Debugger.MESSAGE.WARN);
}
channel.fError = true;
}
}
@ -2848,7 +2892,7 @@ ChipSet.prototype.updateDMA = function(channel)
channel.component = channel.obj = null;
}
if (DEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.DMA | (iDMAChannel == ChipSet.DMA_FDC? Debugger.MESSAGE.FDC : (iDMAChannel == ChipSet.DMA_HDC? Debugger.MESSAGE.HDC : 0))) && channel.xfer == ChipSet.DMA_MODE.XFER_WRITE && channel.sAddrDebug) {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.DMA | (iDMAChannel == ChipSet.DMA_FDC? Debugger.MESSAGE.FDC : (iDMAChannel == ChipSet.DMA_HDC? Debugger.MESSAGE.HDC : 0))) && channel.xfer == ChipSet.DMA_MODE.XFER_WRITE && channel.sAddrDebug) {
this.dbg.message("updateDMA(" + iDMAChannel + ") transferred " + channel.cbDebug + " bytes to " + channel.sAddrDebug);
this.dbg.doDump("db", channel.sAddrDebug, "l" + Math.floor((channel.cbDebug + 15) / 16));
}
@ -2890,7 +2934,9 @@ ChipSet.prototype.inPICLo = function(iPIC, addrFrom)
break;
}
}
this.messagePort(pic.port, null, addrFrom, "PIC" + iPIC, Debugger.MESSAGE.PIC, b);
if (this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.PORT)) {
this.messagePort(pic.port, null, addrFrom, "PIC" + iPIC, Debugger.MESSAGE.PIC, b);
}
return b;
};
@ -2905,7 +2951,9 @@ ChipSet.prototype.inPICLo = function(iPIC, addrFrom)
ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
{
var pic = this.aPICs[iPIC];
this.messagePort(pic.port, bOut, addrFrom, "PIC" + iPIC, Debugger.MESSAGE.PIC);
if (this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.PORT)) {
this.messagePort(pic.port, bOut, addrFrom, "PIC" + iPIC, Debugger.MESSAGE.PIC);
}
if (bOut & ChipSet.PIC_LO.ICW1) {
/*
* This must be an ICW1...
@ -2987,11 +3035,13 @@ ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
}
var nIRQ = (nIRL == null? undefined : pic.nIRQBase + nIRL);
if (pic.bISR & bIREnd) {
if (DEBUG) this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): IRQ " + nIRQ + " going out of service", Debugger.MESSAGE.PIC, nIRQ);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC, nIRQ)) {
this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): IRQ " + nIRQ + " going out of service", Debugger.MESSAGE.PIC, nIRQ);
}
pic.bISR &= ~bIREnd;
this.checkIRR(iPIC);
} else {
if (DEBUG) {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN)) {
this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): unexpected EOI command, IRQ " + nIRQ + " not in service", Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN);
if (this.dbg && !SAMPLER && MAXDEBUG) this.dbg.stopCPU();
}
@ -2999,7 +3049,7 @@ ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
/*
* TODO: Support EOI commands with automatic rotation (eg, ChipSet.PIC_LO.OCW2_EOI_ROT and ChipSet.PIC_LO.OCW2_EOI_ROTSPEC)
*/
if (DEBUG && (bOCW2 & ChipSet.PIC_LO.OCW2_SET_ROTAUTO)) {
if (DEBUG && (bOCW2 & ChipSet.PIC_LO.OCW2_SET_ROTAUTO) && this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN)) {
this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): unsupported OCW2 rotate command: " + str.toHexByte(bOut), Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN);
if (this.dbg) this.dbg.stopCPU();
}
@ -3014,7 +3064,7 @@ ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
/*
* TODO: Remaining commands to support: ChipSet.PIC_LO.OCW2_SET_ROTAUTO and ChipSet.PIC_LO.OCW2_CLR_ROTAUTO
*/
if (DEBUG) {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN)) {
this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): unsupported OCW2 automatic EOI command: " + str.toHexByte(bOut), Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN);
if (this.dbg) this.dbg.stopCPU();
}
@ -3027,7 +3077,9 @@ ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
* that's unfortunate, because I don't support them yet.
*/
if (bOut & (ChipSet.PIC_LO.OCW3_POLL_CMD | ChipSet.PIC_LO.OCW3_SMM_CMD)) {
if (DEBUG) this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): unsupported OCW3 command: " + str.toHexByte(bOut), Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN)) {
this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): unsupported OCW3 command: " + str.toHexByte(bOut), Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN);
}
}
pic.bOCW3 = bOut;
}
@ -3045,7 +3097,9 @@ ChipSet.prototype.inPICHi = function(iPIC, addrFrom)
{
var pic = this.aPICs[iPIC];
var b = pic.bIMR;
this.messagePort(pic.port+1, null, addrFrom, "PIC" + iPIC, Debugger.MESSAGE.PIC, b);
if (this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.PORT)) {
this.messagePort(pic.port+1, null, addrFrom, "PIC" + iPIC, Debugger.MESSAGE.PIC, b);
}
return b;
};
@ -3060,7 +3114,9 @@ ChipSet.prototype.inPICHi = function(iPIC, addrFrom)
ChipSet.prototype.outPICHi = function(iPIC, bOut, addrFrom)
{
var pic = this.aPICs[iPIC];
this.messagePort(pic.port+1, bOut, addrFrom, "PIC" + iPIC, Debugger.MESSAGE.PIC);
if (this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.PORT)) {
this.messagePort(pic.port+1, bOut, addrFrom, "PIC" + iPIC, Debugger.MESSAGE.PIC);
}
if (pic.nICW < pic.aICW.length) {
pic.aICW[pic.nICW++] = bOut;
if (pic.nICW == 2 && (pic.aICW[0] & ChipSet.PIC_LO.ICW1_SNGL))
@ -3118,7 +3174,9 @@ ChipSet.prototype.setIRR = function(nIRQ, nDelay)
var nIRL = nIRQ & 0x7;
var pic = this.aPICs[iPIC];
pic.bIRR |= 1 << nIRL;
if (DEBUG) this.messageDebugger("setIRR(" + nIRQ + ")", Debugger.MESSAGE.PIC, nIRQ);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC, nIRQ)) {
this.messageDebugger("setIRR(" + nIRQ + ")", Debugger.MESSAGE.PIC, nIRQ);
}
pic.nDelay = nDelay || 0;
/*
* When any slave IRR goes high, I'm assuming that the master's slave IRR line should go high as well
@ -3141,7 +3199,9 @@ ChipSet.prototype.clearIRR = function(nIRQ)
var bIRR = (1 << nIRL);
if (pic.bIRR & bIRR) {
pic.bIRR &= ~bIRR;
if (DEBUG) this.messageDebugger("clearIRR(" + nIRQ + ")", Debugger.MESSAGE.PIC, nIRQ);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC, nIRQ)) {
this.messageDebugger("clearIRR(" + nIRQ + ")", Debugger.MESSAGE.PIC, nIRQ);
}
/*
* When all slave IRRs go low, I'm assuming that the master's slave IRR line should go low as well
*/
@ -3237,7 +3297,7 @@ ChipSet.prototype.getIRRVector = function(iPIC)
}
var nIRQ = pic.nIRQBase + nIRL;
if (DEBUG) {
if (DEBUG && this.messageEnabled(0, nIRQ)) {
this.messageDebugger("getIRRVector(): IRQ " + nIRQ + " interrupting @" + str.toHexAddr(this.cpu.regIP, this.cpu.segCS.sel) + " stack=" + str.toHexAddr(this.cpu.regSP, this.cpu.segSS.sel), 0, nIRQ);
}
if (MAXDEBUG && DEBUGGER) {
@ -3273,7 +3333,9 @@ ChipSet.prototype.inTimer = function(iTimer, addrFrom)
}
this.updateTimer(iTimer);
b = timer.countCurrent[timer.countIndex++];
this.messagePort(ChipSet.TIMER0.PORT + iTimer, null, addrFrom, "TIMER" + iTimer, Debugger.MESSAGE.TIMER, b);
if (this.messageEnabled(Debugger.MESSAGE.TIMER | Debugger.MESSAGE.PORT)) {
this.messagePort(ChipSet.TIMER0.PORT + iTimer, null, addrFrom, "TIMER" + iTimer, Debugger.MESSAGE.TIMER, b);
}
return b;
};
@ -3296,8 +3358,9 @@ ChipSet.prototype.inTimer = function(iTimer, addrFrom)
*/
ChipSet.prototype.outTimer = function(iTimer, bOut, addrFrom)
{
this.messagePort(ChipSet.TIMER0.PORT + iTimer, bOut, addrFrom, "TIMER" + iTimer, Debugger.MESSAGE.TIMER);
if (this.messageEnabled(Debugger.MESSAGE.TIMER | Debugger.MESSAGE.PORT)) {
this.messagePort(ChipSet.TIMER0.PORT + iTimer, bOut, addrFrom, "TIMER" + iTimer, Debugger.MESSAGE.TIMER);
}
var timer = this.aTimers[iTimer];
if (timer.countIndex == timer.countBytes) this.resetTimerIndex(iTimer);
timer.countInit[timer.countIndex++] = bOut;
@ -3364,8 +3427,8 @@ ChipSet.prototype.inTimerCtrl = function(port, addrFrom)
*/
ChipSet.prototype.outTimerCtrl = function(port, bOut, addrFrom)
{
this.messagePort(port, bOut, addrFrom, "TIMER_CTRL", Debugger.MESSAGE.TIMER);
this.bTimerCtrl = bOut;
this.messagePort(port, bOut, addrFrom, "TIMER_CTRL", Debugger.MESSAGE.TIMER);
/*
* Extract the SC (Select Counter) bits
*/
@ -3422,7 +3485,9 @@ ChipSet.prototype.outTimerCtrl = function(port, bOut, addrFrom)
timer.countStart[0] = timer.countInit[0];
timer.countStart[1] = timer.countInit[1];
timer.nCyclesStart = this.cpu.getCycles(this.fScaleTimers);
if (DEBUG) this.messageDebugger("TIMER0 count reset @" + timer.nCyclesStart + " cycles", Debugger.MESSAGE.TIMER);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) {
this.messageDebugger("TIMER0 count reset @" + timer.nCyclesStart + " cycles", Debugger.MESSAGE.TIMER);
}
}
}
}
@ -3623,7 +3688,9 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
var ticksElapsed = ((nCycles - timer.nCyclesStart) / this.nTicksDivisor) | 0;
if (ticksElapsed < 0) {
if (DEBUG) this.messageDebugger("updateTimer(" + iTimer + "): negative tick count (" + ticksElapsed + ")", Debugger.MESSAGE.TIMER);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) {
this.messageDebugger("updateTimer(" + iTimer + "): negative tick count (" + ticksElapsed + ")", Debugger.MESSAGE.TIMER);
}
timer.nCyclesStart = nCycles;
ticksElapsed = 0;
}
@ -3641,7 +3708,9 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
*/
if (timer.mode == ChipSet.TIMER_CTRL.MODE0) {
if (count <= 0) count = 0;
if (DEBUG) this.messageDebugger("updateTimer(" + iTimer + "): MODE0 timer count=" + count, Debugger.MESSAGE.TIMER);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) {
this.messageDebugger("updateTimer(" + iTimer + "): MODE0 timer count=" + count, Debugger.MESSAGE.TIMER);
}
if (!count) {
timer.fOUT = true;
timer.fCounting = false;
@ -3674,7 +3743,9 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
if (count <= 0) {
count = countInit + count;
if (count <= 0) {
// this.messageDebugger("updateTimer(" + iTimer + "): underflow=" + count, Debugger.MESSAGE.TIMER);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) {
this.messageDebugger("updateTimer(" + iTimer + "): underflow=" + count, Debugger.MESSAGE.TIMER);
}
count = countInit;
}
timer.countStart[0] = count & 0xff;
@ -3704,7 +3775,9 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
timer.fOUT = !timer.fOUT;
count = countInit + count;
if (count <= 0) {
// this.messageDebugger("updateTimer(" + iTimer + "): underflow=" + count, Debugger.MESSAGE.TIMER);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) {
this.messageDebugger("updateTimer(" + iTimer + "): underflow=" + count, Debugger.MESSAGE.TIMER);
}
count = countInit;
}
if (MAXDEBUG && DEBUGGER && !iTimer) {
@ -3723,7 +3796,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
}
}
if (DEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.TIMER | Debugger.MESSAGE.LOG)) {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER | Debugger.MESSAGE.LOG)) {
this.log("TIMER" + iTimer + " count: " + count + ", ticks: " + ticksElapsed + ", fired: " + (fFired? "true" : "false"));
}
@ -4224,8 +4297,8 @@ ChipSet.prototype.out8042InBuffCmd = function(port, bOut, addrFrom)
break;
default:
if (DEBUG) {
this.messageDebugger("unrecognized 8042 command: " + str.toHexByte(this.b8042InBuff));
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.C8042)) {
this.messageDebugger("unrecognized 8042 command: " + str.toHexByte(this.b8042InBuff), Debugger.MESSAGE.C8042);
if (this.dbg) this.dbg.stopCPU();
}
break;
@ -4447,7 +4520,9 @@ ChipSet.prototype.inCMOSData = function(port, addrFrom)
{
var bAddr = this.bCMOSAddr & ChipSet.CMOS.ADDR.MASK;
var bIn = (bAddr <= ChipSet.CMOS.ADDR.STATUSD? this.getRTCByte(bAddr) : this.abCMOSData[bAddr]);
this.messagePort(port, null, addrFrom, "CMOS_DATA[" + str.toHexByte(bAddr) + "]", Debugger.MESSAGE.CMOS, bIn);
if (this.messageEnabled(Debugger.MESSAGE.CMOS | Debugger.MESSAGE.PORT)) {
this.messagePort(port, null, addrFrom, "CMOS_DATA[" + str.toHexByte(bAddr) + "]", Debugger.MESSAGE.CMOS, bIn);
}
if (addrFrom != null) {
if (bAddr == ChipSet.CMOS.ADDR.STATUSC) {
/*
@ -4480,7 +4555,9 @@ ChipSet.prototype.inCMOSData = function(port, addrFrom)
ChipSet.prototype.outCMOSData = function(port, bOut, addrFrom)
{
var bAddr = this.bCMOSAddr & ChipSet.CMOS.ADDR.MASK;
this.messagePort(port, bOut, addrFrom, "CMOS_DATA[" + str.toHexByte(bAddr) + "]", Debugger.MESSAGE.CMOS);
if (this.messageEnabled(Debugger.MESSAGE.CMOS | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "CMOS_DATA[" + str.toHexByte(bAddr) + "]", Debugger.MESSAGE.CMOS);
}
var bDelta = bOut ^ this.abCMOSData[bAddr];
this.abCMOSData[bAddr] = (bAddr <= ChipSet.CMOS.ADDR.STATUSD? this.setRTCByte(bAddr, bOut) : bOut);
if (bAddr == ChipSet.CMOS.ADDR.STATUSB && (bDelta & ChipSet.CMOS.STATUSB.PIE)) {
@ -4560,7 +4637,7 @@ ChipSet.prototype.outNMI = function(port, bOut, addrFrom)
ChipSet.prototype.intBIOSRTC = function(addr)
{
if (DEBUGGER) {
if (this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.RTC) && this.dbg.messageInt(Debugger.INT.RTC, addr)) {
if (this.messageEnabled(Debugger.MESSAGE.RTC) && this.dbg.messageInt(Debugger.INT.RTC, addr)) {
/*
* By computing AH now, we get the incoming AH value; if we computed it below, along with
* the rest of the register values, we'd get the outgoing AH value, which is not what we want.
@ -4630,13 +4707,17 @@ ChipSet.prototype.setSpeaker = function(fOn)
if (fOn) {
if (this.sourceAudio) {
this.sourceAudio['frequency']['value'] = freq;
this.messageDebugger("speaker set to " + freq + "hz", Debugger.MESSAGE.SPEAKER);
if (this.messageEnabled(Debugger.MESSAGE.SPEAKER)) {
this.messageDebugger("speaker set to " + freq + "hz", Debugger.MESSAGE.SPEAKER);
}
} else {
this.sourceAudio = this.contextAudio['createOscillator']();
this.sourceAudio['type'] = 1; // 0: sine wave, 1: square wave, 2: sawtooth wave, 3: triangle wave
this.sourceAudio['connect'](this.contextAudio['destination']);
this.sourceAudio['frequency']['value'] = freq;
this.messageDebugger("speaker on at " + freq + "hz", Debugger.MESSAGE.SPEAKER);
if (this.messageEnabled(Debugger.MESSAGE.SPEAKER)) {
this.messageDebugger("speaker on at " + freq + "hz", Debugger.MESSAGE.SPEAKER);
}
this.sourceAudio['noteOn'](0); // aka start()
}
} else {
@ -4644,7 +4725,9 @@ ChipSet.prototype.setSpeaker = function(fOn)
this.sourceAudio['noteOff'](0); // aka stop()
this.sourceAudio['disconnect'](); // QUESTION: is this automatic following a stop(), since this particular source cannot be started again?
delete this.sourceAudio; // QUESTION: ditto?
this.messageDebugger("speaker off at " + freq + "hz", Debugger.MESSAGE.SPEAKER);
if (this.messageEnabled(Debugger.MESSAGE.SPEAKER)) {
this.messageDebugger("speaker off at " + freq + "hz", Debugger.MESSAGE.SPEAKER);
}
}
}
} else if (fOn) {
@ -4652,6 +4735,28 @@ ChipSet.prototype.setSpeaker = function(fOn)
}
};
/**
* messageEnabled(bitsMessage, nIRQ)
*
* @this {ChipSet}
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
* @param {number|undefined} [nIRQ] if the message is associated with a particular IRQ #
* @return {boolean}
*/
ChipSet.prototype.messageEnabled = function(bitsMessage, nIRQ)
{
if (DEBUGGER && this.dbg) {
if (bitsMessage == null) {
bitsMessage = Debugger.MESSAGE.CHIPSET;
}
if (nIRQ !== undefined) {
bitsMessage |= (nIRQ == ChipSet.IRQ.TIMER0? Debugger.MESSAGE.TIMER : (nIRQ == ChipSet.IRQ.KBD? Debugger.MESSAGE.KBD : (nIRQ == ChipSet.IRQ.FDC? Debugger.MESSAGE.FDC : 0))) | Debugger.MESSAGE.PIC;
}
return this.dbg.messageEnabled(bitsMessage);
}
return false;
};
/**
* messageDebugger(sMessage, bitsMessage, nIRQ)
*
@ -4668,13 +4773,7 @@ ChipSet.prototype.setSpeaker = function(fOn)
ChipSet.prototype.messageDebugger = function(sMessage, bitsMessage, nIRQ)
{
if (DEBUGGER && this.dbg) {
if (bitsMessage == null) {
bitsMessage = Debugger.MESSAGE.CHIPSET;
}
if (nIRQ !== undefined) {
bitsMessage |= (nIRQ == ChipSet.IRQ.TIMER0? Debugger.MESSAGE.TIMER : (nIRQ == ChipSet.IRQ.KBD? Debugger.MESSAGE.KBD : (nIRQ == ChipSet.IRQ.FDC? Debugger.MESSAGE.FDC : 0))) | Debugger.MESSAGE.PIC;
}
if (this.dbg.messageEnabled(bitsMessage)) this.dbg.message(sMessage);
if (this.messageEnabled(bitsMessage, nIRQ)) this.dbg.message(sMessage);
}
};

View file

@ -150,9 +150,9 @@ function Debugger(parmsDbg)
this.initMessages(parmsDbg['messages']);
/*
* This object is filled in by updateRegValues() whenever we need a fresh snapshot.
* This object is filled in by messageRegs() whenever we need a fresh snapshot.
*/
this.aRegValues = {
this.aMessageRegs = {
"AL":0, "CL":0, "DL":0, "BL":0, "AH":0, "CH":0, "DH":0, "BH":0,
"AX":0, "CX":0, "DX":0, "BX":0, "SP":0, "BP":0, "SI":0, "DI":0,
"ES":0, "CS":0, "SS":0, "DS":0, "IP":0
@ -175,6 +175,9 @@ function Debugger(parmsDbg)
* "live" console window); eg:
*
* $('r')
* $('dw 0:0')
* $('h')
* ...
*/
var dbg = this;
if (window && window['$'] === undefined) {
@ -1607,34 +1610,34 @@ if (DEBUGGER) {
};
/**
* updateRegValues()
* messageRegs()
*
* @this {Debugger}
*/
Debugger.prototype.updateRegValues = function() {
Debugger.prototype.messageRegs = function() {
var cpu = this.cpu;
var asRegs = Debugger.asRegs;
this.aRegValues[asRegs[0]] = str.toHexByte(cpu.regAX & 0xff);
this.aRegValues[asRegs[1]] = str.toHexByte(cpu.regCX & 0xff);
this.aRegValues[asRegs[2]] = str.toHexByte(cpu.regDX & 0xff);
this.aRegValues[asRegs[3]] = str.toHexByte(cpu.regBX & 0xff);
this.aRegValues[asRegs[4]] = str.toHexByte(cpu.regAX >> 8);
this.aRegValues[asRegs[5]] = str.toHexByte(cpu.regCX >> 8);
this.aRegValues[asRegs[6]] = str.toHexByte(cpu.regDX >> 8);
this.aRegValues[asRegs[7]] = str.toHexByte(cpu.regBX >> 8);
this.aRegValues[asRegs[8]] = str.toHexWord(cpu.regAX);
this.aRegValues[asRegs[9]] = str.toHexWord(cpu.regCX);
this.aRegValues[asRegs[10]] = str.toHexWord(cpu.regDX);
this.aRegValues[asRegs[11]] = str.toHexWord(cpu.regBX);
this.aRegValues[asRegs[12]] = str.toHexWord(cpu.regSP);
this.aRegValues[asRegs[13]] = str.toHexWord(cpu.regBP);
this.aRegValues[asRegs[14]] = str.toHexWord(cpu.regSI);
this.aRegValues[asRegs[15]] = str.toHexWord(cpu.regDI);
this.aRegValues[asRegs[16]] = str.toHexWord(cpu.segES.sel);
this.aRegValues[asRegs[17]] = str.toHexWord(cpu.segCS.sel);
this.aRegValues[asRegs[18]] = str.toHexWord(cpu.segSS.sel);
this.aRegValues[asRegs[19]] = str.toHexWord(cpu.segDS.sel);
this.aRegValues[asRegs[20]] = str.toHexWord(cpu.regIP);
this.aMessageRegs[asRegs[0]] = str.toHexByte(cpu.regAX & 0xff);
this.aMessageRegs[asRegs[1]] = str.toHexByte(cpu.regCX & 0xff);
this.aMessageRegs[asRegs[2]] = str.toHexByte(cpu.regDX & 0xff);
this.aMessageRegs[asRegs[3]] = str.toHexByte(cpu.regBX & 0xff);
this.aMessageRegs[asRegs[4]] = str.toHexByte(cpu.regAX >> 8);
this.aMessageRegs[asRegs[5]] = str.toHexByte(cpu.regCX >> 8);
this.aMessageRegs[asRegs[6]] = str.toHexByte(cpu.regDX >> 8);
this.aMessageRegs[asRegs[7]] = str.toHexByte(cpu.regBX >> 8);
this.aMessageRegs[asRegs[8]] = str.toHexWord(cpu.regAX);
this.aMessageRegs[asRegs[9]] = str.toHexWord(cpu.regCX);
this.aMessageRegs[asRegs[10]] = str.toHexWord(cpu.regDX);
this.aMessageRegs[asRegs[11]] = str.toHexWord(cpu.regBX);
this.aMessageRegs[asRegs[12]] = str.toHexWord(cpu.regSP);
this.aMessageRegs[asRegs[13]] = str.toHexWord(cpu.regBP);
this.aMessageRegs[asRegs[14]] = str.toHexWord(cpu.regSI);
this.aMessageRegs[asRegs[15]] = str.toHexWord(cpu.regDI);
this.aMessageRegs[asRegs[16]] = str.toHexWord(cpu.segES.sel);
this.aMessageRegs[asRegs[17]] = str.toHexWord(cpu.segCS.sel);
this.aMessageRegs[asRegs[18]] = str.toHexWord(cpu.segSS.sel);
this.aMessageRegs[asRegs[19]] = str.toHexWord(cpu.segDS.sel);
this.aMessageRegs[asRegs[20]] = str.toHexWord(cpu.regIP);
};
/**
@ -1661,8 +1664,8 @@ if (DEBUGGER) {
var aFuncs = Debugger.INT_FUNCS[nInt];
var sFunc = (aFuncs && aFuncs[AH]) || "";
if (sFunc) {
this.updateRegValues();
sFunc = " " + str.replaceArray(this.aRegValues, sFunc);
this.messageRegs();
sFunc = " " + str.replaceArray(this.aMessageRegs, sFunc);
}
/*
* For purposes of display only, rewind addr to the address of the responsible "INT n" instruction; we
@ -1759,8 +1762,8 @@ if (DEBUGGER) {
}
/*
* We have no idea what the frequency of println() calls might be; all we know is that they easily
* screw up the CPU's careful assumptions about cycles per burst. So we need call yieldCPU() after
* every message, to effectively end the current burst and start fresh.
* screw up the CPU's careful assumptions about cycles per burst. So we call yieldCPU() after every
* message, to effectively end the current burst and start fresh.
*
* TODO: See CPU.calcStartTime() for a discussion of why we might want to call yieldCPU() *before*
* we display the message.
@ -2180,7 +2183,7 @@ if (DEBUGGER) {
};
/**
* checksEnabled(fBreak)
* checksEnabled(fRelease)
*
* This "check" function is called by the CPU; we indicate whether or not every instruction needs to be checked.
*
@ -2189,12 +2192,12 @@ if (DEBUGGER) {
* functions to deal with those breakpoints in the appropriate memory blocks. So I've simplified the test below.
*
* @this {Debugger}
* @param {boolean} [fBreak] is true if the caller really wants to break (default is false)
* @param {boolean} [fRelease] is true for release criteria only; default is false (any criteria)
* @return {boolean} true if every instruction needs to pass through checkInstruction(), false if not
*/
Debugger.prototype.checksEnabled = function(fBreak)
Debugger.prototype.checksEnabled = function(fRelease)
{
return ((DEBUG && !fBreak)? true : (this.aBreakExec.length > 1 || this.messageEnabled(Debugger.MESSAGE.INT) /* || this.aBreakRead.length > 1 || this.aBreakWrite.length > 1 */));
return ((DEBUG && !fRelease)? true : (this.aBreakExec.length > 1 || this.messageEnabled(Debugger.MESSAGE.INT) /* || this.aBreakRead.length > 1 || this.aBreakWrite.length > 1 */));
};
/**
@ -2216,17 +2219,6 @@ if (DEBUGGER) {
*/
if (DEBUG) {
this.assert(!(this.cpu.regAX & ~0xffff) && !(this.cpu.regBX & ~0xffff) && !(this.cpu.regCX & ~0xffff) && !(this.cpu.regDX & ~0xffff), "register out of bounds");
/*
if (!fSkipBP && this.cInstructions == 11303367) {
return true;
}
*/
if (!fSkipBP && MAXDEBUG) {
if (!this.cpu.regIP) {
this.println("suspicious IP");
return true;
}
}
}
if (!fSkipBP && this.checkBreakpoint(addr, this.aBreakExec)) {
@ -2571,12 +2563,20 @@ if (DEBUGGER) {
{
if (!this.findBreakpoint(aBreak, aAddr)) {
/*
* Breakpoint addresses are managed slightly different than other addresses:
* we calculate the physical address at the time the breakpoint is added and save
* it in aAddr[2], so that a breakpoint set in one mode (eg, in real-mode) will still
* work as intended if the mode changes later (eg, to protected-mode).
* We used to calculate the physical address of the breakpoint address now, at the
* time the breakpoint is added, and save it in aAddr[2], so that a breakpoint set in
* one mode (eg, in real-mode) would still work as intended if the mode changed later
* (eg, to protected-mode).
*
* However, that creates difficulties setting protected-mode breakpoints in segments
* that might not be defined yet, or that may move in physical memory; so we're not
* doing this anymore:
*
* aAddr[2] = this.getAddr(aAddr);
*
* The way to create a real-mode breakpoint that will regardless of mode is to use the
* physical address of the real-mode memory location.
*/
aAddr[2] = this.getAddr(aAddr);
aAddr[3] = fTemp;
aBreak.push(aAddr);
if (aBreak != this.aBreakExec) {
@ -2735,7 +2735,7 @@ if (DEBUGGER) {
if (aAddrBreak[3]) {
this.findBreakpoint(aBreak, aAddrBreak, true);
} else if (!fTemp) {
this.println("breakpoint hit: " + this.hexAddr(aAddrBreak) + " (" + aBreak[0] + ")");
this.println("\nbreakpoint hit: " + this.hexAddr(aAddrBreak) + " (" + aBreak[0] + ")");
}
fBreak = true;
break;
@ -2882,7 +2882,7 @@ if (DEBUGGER) {
/*
* There's the occasional immediate byte we don't need to display (eg, the 0x0A
* following an AAM or AAD instruction), so we suppress the byte if it lacks a TYPE_IN
* or TYPE_OUT designation (and TYPE_BOTH, as it name implies, includes both).
* or TYPE_OUT designation (and TYPE_BOTH, as the name implies, includes both).
*/
if (type & Debugger.TYPE_BOTH) {
sOperand = str.toHexByte(this.getByte(aAddr, 1));
@ -3166,6 +3166,7 @@ if (DEBUGGER) {
if (sAddr.charAt(0) == '%') {
sAddr = sAddr.substr(1);
off = -1;
seg = null;
addr = 0;
}
@ -3863,6 +3864,7 @@ if (DEBUGGER) {
Debugger.prototype.doHalt = function(sCount)
{
if (this.bitField.fRunning && sCount === undefined) {
this.println("halting");
this.cpu.stopCPU();
return;
}

View file

@ -774,7 +774,9 @@ FDC.prototype.initController = function(data)
this.regInput = data[i++] || 0; // TODO: Determine if we should default to FDC.REG_INPUT.DISK_CHANGE instead of 0
this.regControl = data[i] || FDC.REG_CONTROL.RATE500K; // default to maximum data rate
if (DEBUG) this.messageDebugger("FDC initialized for " + this.aDrives.length + " drive(s)");
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("FDC initialized for " + this.aDrives.length + " drive(s)");
}
return fSuccess;
};
@ -1279,7 +1281,7 @@ FDC.prototype.loadDiskette = function(iDrive, sDisketteName, sDiskettePath, fAut
if (fAutoMount) {
drive.fAutoMount = true;
this.cAutoMount++;
this.messageDebugger("loading diskette '" + sDisketteName + "'");
if (this.messageEnabled()) this.messageDebugger("loading diskette '" + sDisketteName + "'");
}
drive.fLocal = !!file;
var disk = new Disk(this, drive, DiskAPI.MODE.PRELOAD);
@ -1527,11 +1529,15 @@ FDC.prototype.addDiskHistory = function(sDisketteName, sDiskettePath, disk)
for (i = 0; i < this.aDiskHistory.length; i++) {
if (this.aDiskHistory[i][1] == sDiskettePath) {
var nChanges = disk.restore(this.aDiskHistory[i][2]);
if (DEBUG) this.messageDebugger("disk '" + sDisketteName + "' restored from history (" + nChanges + " changes)");
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("disk '" + sDisketteName + "' restored from history (" + nChanges + " changes)");
}
return;
}
}
if (DEBUG) this.messageDebugger("disk '" + sDisketteName + "' added to history (nothing to restore)");
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("disk '" + sDisketteName + "' added to history (nothing to restore)");
}
this.aDiskHistory[i] = [sDisketteName, sDiskettePath, []];
};
@ -1548,11 +1554,15 @@ FDC.prototype.removeDiskHistory = function(sDisketteName, sDiskettePath)
for (i = 0; i < this.aDiskHistory.length; i++) {
if (this.aDiskHistory[i][1] == sDiskettePath) {
this.aDiskHistory.splice(i, 1);
if (DEBUG) this.messageDebugger("disk '" + sDisketteName + "' removed from history");
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("disk '" + sDisketteName + "' removed from history");
}
return;
}
}
if (DEBUG) this.messageDebugger("unable to remove disk '" + sDisketteName + "' from history (" + sDiskettePath + ")");
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("unable to remove disk '" + sDisketteName + "' from history (" + sDiskettePath + ")");
}
};
/**
@ -1569,7 +1579,9 @@ FDC.prototype.updateDiskHistory = function(sDisketteName, sDiskettePath, disk)
for (i = 0; i < this.aDiskHistory.length; i++) {
if (this.aDiskHistory[i][1] == sDiskettePath) {
this.aDiskHistory[i][2] = disk.save();
if (DEBUG) this.messageDebugger("disk '" + sDisketteName + "' updated in history");
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("disk '" + sDisketteName + "' updated in history");
}
return;
}
}
@ -1579,7 +1591,9 @@ FDC.prototype.updateDiskHistory = function(sDisketteName, sDiskettePath, disk)
* unload, and then reload/remount. And since unloadDrive's normal behavior is to call updateDiskHistory()
* before unloading, the fact that the disk is no longer listed here can't be treated as an error.
*/
if (DEBUG) this.messageDebugger("unable to update disk '" + sDisketteName + "' in history (" + sDiskettePath + ")");
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("unable to update disk '" + sDisketteName + "' in history (" + sDiskettePath + ")");
}
};
/**
@ -1668,7 +1682,9 @@ FDC.prototype.inFDCData = function(port, addrFrom)
if (this.regOutput & FDC.REG_OUTPUT.INT_ENABLE) {
if (this.chipset) this.chipset.clearIRR(ChipSet.IRQ.FDC);
}
this.messagePort(port, null, addrFrom, "DATA[" + this.regDataIndex + "]", bIn);
if (this.messageEnabled()) {
this.messagePort(port, null, addrFrom, "DATA[" + this.regDataIndex + "]", bIn);
}
if (++this.regDataIndex >= this.regDataTotal) {
this.regStatus &= ~(FDC.REG_STATUS.READ_DATA | FDC.REG_STATUS.BUSY);
this.regDataIndex = this.regDataTotal = 0;
@ -1686,7 +1702,9 @@ FDC.prototype.inFDCData = function(port, addrFrom)
*/
FDC.prototype.outFDCData = function(port, bOut, addrFrom)
{
this.messagePort(port, bOut, addrFrom, "DATA[" + this.regDataTotal + "]");
if (this.messageEnabled()) {
this.messagePort(port, bOut, addrFrom, "DATA[" + this.regDataTotal + "]");
}
if (this.regDataTotal < this.regDataArray.length) {
this.regDataArray[this.regDataTotal++] = bOut;
@ -1699,7 +1717,7 @@ FDC.prototype.outFDCData = function(port, bOut, addrFrom)
}
return;
}
if (DEBUG) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("unsupported FDC command: " + str.toHexByte(bCmd));
if (DEBUGGER) this.cpu.stopCPU();
}
@ -1928,7 +1946,7 @@ FDC.prototype.doCmd = function()
break;
default:
if (DEBUG) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("FDC operation unsupported (command=0x: " + str.toHexByte(bCmd) + ")");
if (DEBUGGER) this.cpu.stopCPU();
}
@ -2007,7 +2025,7 @@ FDC.prototype.popCmd = function(name)
{
if (DEBUG) this.assert((!this.regDataIndex || name !== undefined) && this.regDataIndex < this.regDataTotal);
var bCmd = this.regDataArray[this.regDataIndex];
if (DEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.FDC)) {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PORT)) {
var bCmdMasked = bCmd & FDC.REG_DATA.CMD.MASK;
if (!name && !this.regDataIndex && FDC.aCmdInfo[bCmdMasked]) name = FDC.aCmdInfo[bCmdMasked].name;
this.messageDebugger("FDC.CMD[" + (name || this.regDataIndex) + "]: 0x" + str.toHexByte(bCmd), Debugger.MESSAGE.PORT);
@ -2061,7 +2079,9 @@ FDC.prototype.beginResult = function()
*/
FDC.prototype.pushResult = function(bResult, name)
{
if (DEBUG) this.messageDebugger("FDC.RES[" + (name || this.regDataTotal) + "]: 0x" + str.toHexByte(bResult), Debugger.MESSAGE.PORT);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PORT)) {
this.messageDebugger("FDC.RES[" + (name || this.regDataTotal) + "]: 0x" + str.toHexByte(bResult), Debugger.MESSAGE.PORT);
}
this.regDataArray[this.regDataTotal++] = bResult;
};
@ -2183,7 +2203,9 @@ FDC.prototype.doRead = function(drive)
*/
drive.resCode = FDC.REG_DATA.RES.NOT_READY | FDC.REG_DATA.RES.INCOMPLETE;
if (DEBUG) this.messageDebugger("FDC.doRead(" + drive.bCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")", Debugger.MESSAGE.OTHER);
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("FDC.doRead(" + drive.bCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")");
}
if (drive.disk) {
drive.sector = null;
@ -2205,7 +2227,9 @@ FDC.prototype.doWrite = function(drive)
{
drive.resCode = FDC.REG_DATA.RES.NOT_READY | FDC.REG_DATA.RES.INCOMPLETE;
if (DEBUG) this.messageDebugger("FDC.doWrite(" + drive.bCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")", Debugger.MESSAGE.OTHER);
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("FDC.doWrite(" + drive.bCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")");
}
if (drive.disk) {
if (drive.disk.fWriteProtected) {
@ -2403,7 +2427,9 @@ FDC.prototype.writeFormat = function(drive, b)
drive.bSector = drive.abFormat[2]; // R
drive.nBytes = 128 << drive.abFormat[3];// N (0 => 128, 1 => 256, 2 => 512, 3 => 1024)
drive.cbFormat = 0;
if (DEBUG) this.messageDebugger("writeFormat(head=" + str.toHexByte(drive.bHead) + ",cyl=" + str.toHexByte(drive.bCylinder) + ",sec=" + str.toHexByte(drive.bSector) + ",len=" + str.toHexWord(drive.nBytes) + ")");
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("writeFormat(head=" + str.toHexByte(drive.bHead) + ",cyl=" + str.toHexByte(drive.bCylinder) + ",sec=" + str.toHexByte(drive.bSector) + ",len=" + str.toHexWord(drive.nBytes) + ")");
}
for (var i = 0; i < drive.nBytes; i++) {
if (this.writeByte(drive, drive.bFiller) < 0) {
return -1;
@ -2415,6 +2441,26 @@ FDC.prototype.writeFormat = function(drive, b)
return b;
};
/**
* messageEnabled(bitsMessage)
*
* @this {FDC}
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
* @return {boolean}
*/
FDC.prototype.messageEnabled = function(bitsMessage)
{
if (DEBUGGER && this.dbg) {
if (bitsMessage == null) {
bitsMessage = Debugger.MESSAGE.FDC;
} else {
bitsMessage |= Debugger.MESSAGE.FDC;
}
return this.dbg.messageEnabled(bitsMessage);
}
return false;
};
/**
* messageDebugger(sMessage, bitsMessage)
*

View file

@ -1637,24 +1637,24 @@ X86CPU.prototype.setPS = function(regPS)
/*
* OS/2 1.0 discriminates between an 80286 and an 80386 based on whether an IRET in real-mode that
* pops 0xF000 into the flags is able to set *any* of flag bits 12-15: if yes, then OS/2 declares the
* the CPU an 80386. Therefore, in real-mode, we must effectively zero all incoming bits 12-15.
* pops 0xF000 into the flags is able to set *any* of flag bits 12-15: if it can, then OS/2 declares
* the the CPU an 80386. Therefore, in real-mode, we must zero all incoming bits 12-15.
*
* This has the added benefit of relieving us from zeroing the effective IOPL (this.nIOPL) in real-mode,
* since we're zeroing the IOPL bits up front; so that code below is commented out now.
* This has the added benefit of relieving us from having to zero the effective IOPL (this.nIOPL)
* whenever we're in real-mode, since we're zeroing the IOPL bits up front now.
*/
if (!(this.regMSW & X86.MSW.PE)) {
regPS &= ~(X86.PS.IOPL.MASK | X86.PS.NT | X86.PS.BIT15);
}
/*
* Since PS.IOPL and PS.IF are part of PS_DIRECT, we need to take care of any 80286-specific checks before
* setting the PS_DIRECT bits from the incoming regPS bits. Specifically, PS.IOPL is unchanged if CPL > 0,
* and PS.IF is unchanged if CPL > IOPL.
* Since PS.IOPL and PS.IF are part of PS_DIRECT, we need to take care of any 80286-specific behaviors
* before setting the PS_DIRECT bits from the incoming regPS bits.
*
* Specifically, PS.IOPL is unchanged if CPL > 0, and PS.IF is unchanged if CPL > IOPL.
*/
if (!this.segCS.cpl) {
this.nIOPL = (regPS & X86.PS.IOPL.MASK) >> X86.PS.IOPL.SHIFT; // IOPL allowed to change
// if (this.nIOPL && !(this.regMSW & X86.MSW.PE)) this.nIOPL = 0; // effective IOPL remains 0
} else {
regPS = (regPS & ~X86.PS.IOPL.MASK) | (this.regPS & X86.PS.IOPL.MASK); // IOPL not allowed to change
}

View file

@ -487,7 +487,7 @@ var X86Help = {
*/
opHelpIRET: function() {
/*
* TODO: We assess a fixed cycle cost up front, because at the moment, opHelpSwitchTSS() doesn't assess anything.
* TODO: We assess a fixed cycle cost up front, because at the moment, switchTSS() doesn't assess anything.
*/
this.nStepCycles -= this.CYCLES.nOpCyclesIRet;
if (this.regMSW & X86.MSW.PE) {
@ -634,7 +634,7 @@ var X86Help = {
}
if (fDebugger && this.dbg.messageEnabled(bitsMessage) || !fDebugger && fHalt) {
var sMessage = "Fault " + str.toHexByte(nFault) + (nError != null? " (" + str.toHexWord(nError) + ")" : "") + " on opcode 0x" + str.toHexByte(bOpcode) + " at " + str.toHexAddr(this.regIP, this.segCS.sel) + " (%" + str.toHex(this.regEIP, 6) + ")";
var sMessage = (fHalt? '\n' : '') + "Fault " + str.toHexByte(nFault) + (nError != null? " (" + str.toHexWord(nError) + ")" : "") + " on opcode 0x" + str.toHexByte(bOpcode) + " at " + str.toHexAddr(this.regIP, this.segCS.sel) + " (%" + str.toHex(this.regEIP, 6) + ")";
if (fDebugger) {
this.messageDebugger(sMessage, bitsMessage);
if (fHalt) {

View file

@ -50,6 +50,7 @@ if (typeof module !== 'undefined') {
function X86Seg(cpu, id, sName, fProt)
{
this.cpu = cpu;
this.dbg = cpu.dbg;
this.id = id;
this.sName = sName || "";
this.sel = 0;
@ -154,18 +155,30 @@ X86Seg.loadProt = function loadProt(sel, fSuppress)
addrDT = cpu.segLDT.base;
addrDTLimit = addrDT + cpu.segLDT.limit;
}
var addrDesc = addrDT + (sel & X86.SEL.MASK);
if (addrDesc + 7 <= addrDTLimit) {
/*
* TODO: This is only the first of many steps toward accurately counting cycles in protected mode;
* I simply noted that "POP segreg" takes 5 cycles in real mode and 20 in protected mode, so I'm
* starting with a 15-cycle difference. Obviously the difference will be much greater when the load fails.
*/
if (!fSuppress) cpu.nStepCycles -= 15;
return this.loadDesc8(addrDesc, sel);
}
if (!fSuppress) {
X86Help.opHelpFault.call(this.cpu, X86.EXCEPTION.GP_FAULT, sel);
/*
* The ROM BIOS POST executes some test code in protected-mode without properly initializing the LDT,
* which has no bearing on the ROM's own code, because it never loads any LDT selectors, but if at the same
* time our Debugger attempts to validate a selector in one of its breakpoints, that could cause some
* grief here. We avoid that grief by 1) relying on the Debugger setting fSuppress to true, and 2) skipping
* segment lookup if the descriptor table being referenced is zero.
*
* TODO: This could probably be simplified to a test of addrDT; please note, however, that there's nothing
* in the design of the CPU that prevents the GDT or LDT being located at physical address zero.
*/
if (!fSuppress || addrDT) {
var addrDesc = addrDT + (sel & X86.SEL.MASK);
if (addrDesc + 7 <= addrDTLimit) {
/*
* TODO: This is only the first of many steps toward accurately counting cycles in protected mode;
* I simply noted that "POP segreg" takes 5 cycles in real mode and 20 in protected mode, so I'm
* starting with a 15-cycle difference. Obviously the difference will be much greater when the load fails.
*/
if (!fSuppress) cpu.nStepCycles -= 15;
return this.loadDesc8(addrDesc, sel, fSuppress);
}
if (!fSuppress) {
X86Help.opHelpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel);
}
}
return null;
};
@ -214,7 +227,7 @@ X86Seg.loadProtIDT = function loadProtIDT(nIDT)
if (addrDesc + 7 <= cpu.addrIDTLimit) {
return this.loadDesc8(addrDesc, nIDT);
}
X86Help.opHelpFault.call(this.cpu, X86.EXCEPTION.GP_FAULT, nIDT | X86.ERRCODE.IDT | X86.ERRCODE.EXT, true);
X86Help.opHelpFault.call(cpu, X86.EXCEPTION.GP_FAULT, nIDT | X86.ERRCODE.IDT | X86.ERRCODE.EXT, true);
return null;
};
@ -383,8 +396,8 @@ X86Seg.switchTSS = function switchTSS(selNew, fNest)
return false;
}
var addrNew = cpu.segTSS.base;
if (DEBUG) {
cpu.messageDebugger((fNest? "Task switch" : "Task return") + ": TR " + str.toHexWord(selOld) + " (%" + str.toHex(addrOld, 6) + "), new TR " + str.toHexWord(selNew) + " (%" + str.toHex(addrNew, 6) + ")", Debugger.MESSAGE.TSS);
if (DEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.TSS)) {
this.dbg.message((fNest? "Task switch" : "Task return") + ": TR " + str.toHexWord(selOld) + " (%" + str.toHex(addrOld, 6) + "), new TR " + str.toHexWord(selNew) + " (%" + str.toHex(addrNew, 6) + ")");
}
if (fNest) {
if (cpu.segTSS.type == X86.DESC.ACC.TYPE.TSS_BUSY) {
@ -503,7 +516,7 @@ X86Seg.prototype.loadDesc6 = function(addrDesc, sel)
};
/**
* loadDesc8(addrDesc, sel)
* loadDesc8(addrDesc, sel, fSuppress)
*
* Used to load a protected-mode selector that refers to an 8-byte "descriptor table" (GDT, LDT, IDT) entry:
*
@ -517,9 +530,10 @@ X86Seg.prototype.loadDesc6 = function(addrDesc, sel)
* @this {X86Seg}
* @param {number} addrDesc is the descriptor address
* @param {number} sel is the associated selector
* @param {boolean} [fSuppress] is true to suppress any errors, cycle assessment, etc
* @return {number|null} base address of selected segment, or null if error
*/
X86Seg.prototype.loadDesc8 = function(addrDesc, sel)
X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
{
var cpu = this.cpu;
var limit = cpu.getWord(addrDesc + X86.DESC.LIMIT.OFFSET);
@ -599,7 +613,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel)
return this.base;
}
if (DEBUG) cpu.assert(false);
X86Help.opHelpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, true);
if (!fSuppress) X86Help.opHelpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, true);
base = null;
break;
}
@ -644,7 +658,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel)
return this.base;
}
if (DEBUG) cpu.assert(false);
X86Help.opHelpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel | X86.ERRCODE.EXT, true);
if (!fSuppress) X86Help.opHelpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel | X86.ERRCODE.EXT, true);
base = null;
break;
}
@ -656,7 +670,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel)
return this.base;
}
else {
X86Help.opHelpFault.call(this.cpu, X86.EXCEPTION.GP_FAULT, sel, true);
if (!fSuppress) X86Help.opHelpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, true);
base = null;
break;
}
@ -665,7 +679,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel)
else if (this.id == X86Seg.ID.DATA) {
if (selMasked) {
if (type < X86.DESC.ACC.TYPE.DATA_READONLY || (type & (X86.DESC.ACC.TYPE.CODE | X86.DESC.ACC.TYPE.READABLE)) == X86.DESC.ACC.TYPE.CODE) {
X86Help.opHelpFault.call(this.cpu, X86.EXCEPTION.GP_FAULT, sel, true);
if (!fSuppress) X86Help.opHelpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, true);
base = null;
break;
}
@ -673,14 +687,14 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel)
}
else if (this.id == X86Seg.ID.STACK) {
if (!selMasked || type < X86.DESC.ACC.TYPE.DATA_READONLY || (type & (X86.DESC.ACC.TYPE.CODE | X86.DESC.ACC.TYPE.READABLE)) == X86.DESC.ACC.TYPE.CODE) {
X86Help.opHelpFault.call(this.cpu, X86.EXCEPTION.GP_FAULT, sel, true);
if (!fSuppress) X86Help.opHelpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, true);
base = null;
break;
}
}
else if (this.id == X86Seg.ID.TSS) {
if (!selMasked || type != X86.DESC.ACC.TYPE.TSS && type != X86.DESC.ACC.TYPE.TSS_BUSY) {
X86Help.opHelpFault.call(this.cpu, X86.EXCEPTION.TS_FAULT, sel, true);
if (!fSuppress) X86Help.opHelpFault.call(cpu, X86.EXCEPTION.TS_FAULT, sel, true);
base = null;
break;
}
@ -703,7 +717,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel)
this.updateMode();
break;
}
this.messageDebugger(sel, base, limit, acc, ext);
if (!fSuppress) this.messageDebugger(sel, base, limit, acc, ext);
return base;
};
@ -830,11 +844,11 @@ X86Seg.prototype.updateMode = function(fProt)
X86Seg.prototype.messageDebugger = function(sel, base, limit, acc, ext)
{
if (DEBUG) {
if (DEBUGGER) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.SEG)) {
var ch = (this.sName.length < 3? " " : "");
var sDPL = " dpl=" + this.dpl;
if (this.id == X86Seg.ID.CODE) sDPL += " cpl=" + this.cpl;
this.cpu.messageDebugger("loadSeg(" + this.sName + "):" + ch + "sel=" + str.toHexWord(sel) + " base=" + str.toHex(base) + " limit=" + str.toHexWord(limit) + " acc=" + str.toHexWord(acc) + sDPL, Debugger.MESSAGE.SEG);
this.dbg.message("loadSeg(" + this.sName + "):" + ch + "sel=" + str.toHexWord(sel) + " base=" + str.toHex(base) + " limit=" + str.toHexWord(limit) + " acc=" + str.toHexWord(acc) + sDPL);
}
this.cpu.assert(/* base != null && */ (!ext || ext == X86.DESC.EXT.AVAIL));
}

View file

@ -719,9 +719,17 @@ Component.prototype = {
if (DEBUGGER && this.dbg) {
this.dbg.stopCPU(s, true);
/*
* Why do we throw an Error only to immediately catch it and ignore it? Simply to give our IDE
* the opportunity to stop and smell the roses. If the user has no desire to stop on assertions,
* then yes, consider this a giant NO-OP.
* Why do we throw an Error only to immediately catch and ignore it? Simply to give
* any IDE the opportunity to inspect the application's state. Even when the IDE has
* control, you should still be able to invoke Debugger commands from the IDE's REPL,
* using the '$' global function that the Debugger constructor sets up; eg:
*
* $('r')
* $('dw 0:0')
* $('h')
* ...
*
* If you have no desire to stop on assertions, then yes, consider this a giant no-op.
*/
try {
throw new Error(s);