It is now possible to re-attach or re-load the current paper tape; re-attaching means repositioning it at the beginning, and re-loading means loading it into RAM again. Note that whenever you reload a tape, it's HIGHLY recommended that you reset the machine first, too.
This commit is contained in:
parent
dbe987dbc7
commit
de916981f3
8 changed files with 339 additions and 283 deletions
|
|
@ -1168,9 +1168,11 @@ CPUPDP11.prototype.stepCPU = function(nMinCycles)
|
|||
*
|
||||
* @this {CPUPDP11}
|
||||
* @param {boolean} [fComplete]
|
||||
* @return {boolean} true if the CPU was stopped, false if it was already stopped
|
||||
*/
|
||||
CPUPDP11.prototype.stopCPU = function(fComplete)
|
||||
{
|
||||
var fStopped = false;
|
||||
if (this.flags.running) {
|
||||
this.endBurst();
|
||||
this.addCycles(this.nRunCycles);
|
||||
|
|
@ -1181,8 +1183,10 @@ CPUPDP11.prototype.stopCPU = function(fComplete)
|
|||
if (this.cmp) {
|
||||
this.cmp.stop(usr.getTime(), this.getCycles());
|
||||
}
|
||||
fStopped = true;
|
||||
}
|
||||
this.flags.complete = fComplete;
|
||||
return fStopped;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ CPUStatePDP11.prototype.resetRegs = function()
|
|||
this.mmuMask = 0x3ffff;
|
||||
this.mmuMemorySize = BusPDP11.IOPAGE_18BIT;
|
||||
|
||||
this.opFlags |= PDP11.OPFLAG.INTQ;
|
||||
this.resetTriggers();
|
||||
|
||||
if (this.bus) this.setMemoryAccess();
|
||||
};
|
||||
|
|
@ -383,10 +383,15 @@ CPUStatePDP11.prototype.setReset = function(addr, fReset)
|
|||
this.setPC(addr);
|
||||
if (!fReset && this.dbg) {
|
||||
/*
|
||||
* TODO: Review the decision to always stop the CPU if the Debugger is loaded.
|
||||
* TODO: Review the decision to always stop the CPU if the Debugger is loaded. Note that
|
||||
* when stopCPU() stops a running CPU, the Debugger gets notified, so again, no need to notify it here.
|
||||
*
|
||||
* TODO: There are more serious problems to deal with if another component is slamming a new PC down
|
||||
* the CPU's throat (presumably while also dropping some new code into RAM) while the CPU was still running;
|
||||
* we should probably force a complete reset if the CPU is running, but for now, it's up to the user
|
||||
* to hit the reset button themselves.
|
||||
*/
|
||||
this.stopCPU();
|
||||
this.dbg.updateStatus();
|
||||
if (!this.stopCPU()) this.dbg.updateStatus();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -765,12 +770,25 @@ CPUStatePDP11.prototype.checkTriggers = function(priority)
|
|||
};
|
||||
|
||||
/**
|
||||
* checkInterrupts()
|
||||
* resetTriggers(priority)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
*/
|
||||
CPUStatePDP11.prototype.resetTriggers = function()
|
||||
{
|
||||
this.triggerNext = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* checkInterrupts()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @return {boolean} true if an interrupt was dispatched, false if not
|
||||
*/
|
||||
CPUStatePDP11.prototype.checkInterrupts = function()
|
||||
{
|
||||
var fInterrupt = false;
|
||||
|
||||
if (this.opFlags & PDP11.OPFLAG.INTQ) {
|
||||
this.opFlags &= ~PDP11.OPFLAG.INTQ;
|
||||
|
||||
|
|
@ -785,6 +803,7 @@ CPUStatePDP11.prototype.checkInterrupts = function()
|
|||
|
||||
if (this.dispatchInterrupt(vector, priority)) {
|
||||
if (trigger) this.removeTrigger(trigger);
|
||||
fInterrupt = true;
|
||||
}
|
||||
}
|
||||
else if (this.opFlags & PDP11.OPFLAG.INTQ_SPL) {
|
||||
|
|
@ -794,6 +813,7 @@ CPUStatePDP11.prototype.checkInterrupts = function()
|
|||
*/
|
||||
this.opFlags++;
|
||||
}
|
||||
return fInterrupt;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -879,7 +899,7 @@ CPUStatePDP11.prototype.setPSW = function(newPSW)
|
|||
this.regPSW = newPSW;
|
||||
|
||||
/*
|
||||
* Trigger a call to checkInterrupts(), just in case.
|
||||
* Trigger (no pun intended) a call to checkInterrupts(), just in case.
|
||||
*
|
||||
* TODO: I think this is overdone; if you set a breakpoint on checkInterrupts(), you'll see that a significant
|
||||
* percentage of calls do nothing. For example, you'll usually see a spurious checkInterrupts() immediately after
|
||||
|
|
@ -2050,7 +2070,11 @@ CPUStatePDP11.prototype.writeDstWord = function(opCode, data)
|
|||
CPUStatePDP11.prototype.branch = function(opCode, condition)
|
||||
{
|
||||
if (condition) {
|
||||
this.setPC(this.getPC() + ((opCode << 24) >> 23));
|
||||
var off = ((opCode << 24) >> 23);
|
||||
if (DEBUG && DEBUGGER && this.dbg && off == -2) {
|
||||
this.dbg.stopInstruction("branch to self");
|
||||
}
|
||||
this.setPC(this.getPC() + off);
|
||||
this.nStepCycles -= 2;
|
||||
}
|
||||
this.nStepCycles -= (2 + 1);
|
||||
|
|
@ -2117,7 +2141,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
this.stopCPU();
|
||||
break;
|
||||
}
|
||||
nDebugState = 1;
|
||||
if (!nDebugState) nDebugState++;
|
||||
nDebugCheck++;
|
||||
}
|
||||
|
||||
|
|
@ -2150,7 +2174,14 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
|
|||
* interrupting the natural flow of instructions whenever the Debugger is stepping through code.
|
||||
*/
|
||||
if ((this.opFlags & (PDP11.OPFLAG.INTQ_SPL | PDP11.OPFLAG.INTQ | PDP11.OPFLAG.WAIT)) /*&& nMinCycles*/) {
|
||||
this.checkInterrupts();
|
||||
if (this.checkInterrupts()) {
|
||||
/*
|
||||
* Since an interrupt was just dispatched, altering the normal flow of time and changing
|
||||
* the future as we knew it, let's break out immediately if we're single-stepping, so that
|
||||
* the Debugger gets to see the first instruction of the interrupt handler.
|
||||
*/
|
||||
if (nDebugState < 0) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1596,6 +1596,7 @@ if (DEBUGGER) {
|
|||
this.updateStatus(true);
|
||||
this.setFocus();
|
||||
this.clearTempBreakpoint(this.cpu.getPC());
|
||||
this.sMessagePrev = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1679,18 +1680,20 @@ if (DEBUGGER) {
|
|||
};
|
||||
|
||||
/**
|
||||
* stopInstruction()
|
||||
* stopInstruction(sMessage)
|
||||
*
|
||||
* TODO: Currently, the only way to prevent this call from stopping the CPU is when you're single-stepping.
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
* @param {string} [sMessage]
|
||||
* @return {boolean} true if stopping is enabled, false if not
|
||||
*/
|
||||
DebuggerPDP11.prototype.stopInstruction = function()
|
||||
DebuggerPDP11.prototype.stopInstruction = function(sMessage)
|
||||
{
|
||||
var cpu = this.cpu;
|
||||
if (cpu.isRunning()) {
|
||||
cpu.setPC(this.cpu.getLastPC());
|
||||
if (sMessage) this.println(sMessage);
|
||||
this.stopCPU();
|
||||
/*
|
||||
* TODO: Review the appropriate-ness of throwing a bogus vector number in order to immediately stop
|
||||
|
|
|
|||
|
|
@ -82,6 +82,13 @@ function PC11(parms)
|
|||
this.sTapeSource = PC11.SOURCE.NONE;
|
||||
this.nTapeTarget = PC11.TARGET.NONE;
|
||||
this.sTapeName = this.sTapePath = "";
|
||||
|
||||
/*
|
||||
* These next few variables simply keep track of the previous parameters to parseTape(),
|
||||
* so that we can easily reparse the previous tape as needed.
|
||||
*/
|
||||
this.aBytes = this.addrLoad = this.addrExec = null;
|
||||
|
||||
this.nLastPercent = -1; // ensure the first displayProgress() displays something
|
||||
|
||||
/*
|
||||
|
|
@ -447,7 +454,15 @@ PC11.prototype.loadTape = function(sTapeName, sTapePath, nTapeTarget, fAutoMount
|
|||
}
|
||||
}
|
||||
}
|
||||
if (nResult) this.status(this.nTapeTarget == PC11.TARGET.READER? "tape attached" : "tape loaded");
|
||||
if (nResult) {
|
||||
/*
|
||||
* Now that we're calling parseTape() again (so that the current tape can either be restarted on
|
||||
* the reader or reloaded into RAM), we can also rely on it to display an appropriate status message, too.
|
||||
*
|
||||
* this.status(this.nTapeTarget == PC11.TARGET.READER? "tape attached" : "tape loaded");
|
||||
*/
|
||||
this.parseTape(this.sTapeName, this.sTapePath, this.nTapeTarget, this.aBytes, this.addrLoad, this.addrExec);
|
||||
}
|
||||
return nResult;
|
||||
};
|
||||
|
||||
|
|
@ -674,6 +689,9 @@ PC11.prototype.parseTape = function(sTapeName, sTapePath, nTapeTarget, aBytes, a
|
|||
this.sTapeName = sTapeName;
|
||||
this.sTapePath = sTapePath;
|
||||
this.nTapeTarget = nTapeTarget;
|
||||
this.aBytes = aBytes;
|
||||
this.addrLoad = addrLoad;
|
||||
this.addrExec = addrExec;
|
||||
|
||||
if (nTapeTarget == PC11.TARGET.MEMORY) {
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue