Starting on 1.16.1
This commit is contained in:
parent
6c6fccdbdd
commit
6248972684
121 changed files with 1261 additions and 1091 deletions
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue