Added resume support for saving/restoring all active timers and IRQs, along with the run/stop state of the CPU
This commit is contained in:
parent
fac5c3c57d
commit
bb24ccaca6
12 changed files with 844 additions and 671 deletions
|
|
@ -853,7 +853,10 @@ class ComputerPDP11 extends Component {
|
|||
* after they're no longer ready.
|
||||
*/
|
||||
if (this.cpu && this.cpu.powerDown) {
|
||||
if (fShutdown) this.cpu.stopCPU();
|
||||
if (fShutdown) {
|
||||
if (fSave) this.cpu.flags.autoStart = this.cpu.flags.running;
|
||||
this.cpu.stopCPU();
|
||||
}
|
||||
data = this.cpu.powerDown(fSave, fShutdown);
|
||||
if (typeof data === "object") stateComputer.set(this.cpu.id, data);
|
||||
if (fShutdown) {
|
||||
|
|
|
|||
|
|
@ -120,8 +120,7 @@ class CPUPDP11 extends Component {
|
|||
/*
|
||||
* We add a number of flags to the set initialized by Component
|
||||
*/
|
||||
this.flags.running = false;
|
||||
this.flags.starting = false;
|
||||
this.flags.running = this.flags.starting = false;
|
||||
this.flags.autoStart = parmsCPU['autoStart'];
|
||||
if (typeof this.flags.autoStart == "string") this.flags.autoStart = (this.flags.autoStart == "true");
|
||||
|
||||
|
|
@ -996,6 +995,37 @@ class CPUPDP11 extends Component {
|
|||
return nCycles;
|
||||
}
|
||||
|
||||
/**
|
||||
* saveTimers()
|
||||
*
|
||||
* @this {CPUPDP11}
|
||||
* @return {Array.<number>}
|
||||
*/
|
||||
saveTimers()
|
||||
{
|
||||
var aTimerCycles = [];
|
||||
for (var i = 0; i < this.aTimers.length; i++) {
|
||||
var timer = this.aTimers[i];
|
||||
aTimerCycles.push(timer[0]);
|
||||
}
|
||||
return aTimerCycles;
|
||||
}
|
||||
|
||||
/**
|
||||
* restoreTimers(aTimerCycles)
|
||||
*
|
||||
* @this {CPUPDP11}
|
||||
* @param {Array.<number>} aTimerCycles
|
||||
*/
|
||||
restoreTimers(aTimerCycles)
|
||||
{
|
||||
this.assert(aTimerCycles.length === this.aTimers.length);
|
||||
for (var i = 0; i < this.aTimers.length && i < aTimerCycles.length; i++) {
|
||||
var timer = this.aTimers[i];
|
||||
timer[0] = aTimerCycles[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* updateTimers(nCycles)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1128,7 +1128,7 @@ PDP11.opDIV = function(opCode)
|
|||
this.regsGen[reg] = this.regsGen[reg | 1] = 1; // etc
|
||||
}
|
||||
}
|
||||
this.nStepCycles -= (52 + 1); // 52 is the mean of the shortest and longest times
|
||||
this.nStepCycles -= (52 + 1); // 52 is the average of the shortest and longest times
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -117,25 +117,22 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
* These properties will be initialized by initCPU()
|
||||
*/
|
||||
this.flagC = this.flagV = this.flagZ = this.flagN = 0;
|
||||
this.regPSW = 0;
|
||||
this.regsGen = this.regsAlt = this.regsAltStack = [];
|
||||
this.pswMode = 0;
|
||||
this.mapMMR3 = [];
|
||||
this.mmuPDR = this.mmuPAR = this.regsUniMap = this.regsControl = [];
|
||||
this.regMBR = 0;
|
||||
this.opFlags = 0;
|
||||
this.srcMode = this.srcReg = 0;
|
||||
this.dstMode = this.dstReg = this.dstAddr = 0;
|
||||
this.regPSW = this.pswMode = 0;
|
||||
this.pswTrap = 0;
|
||||
this.regsGen = this.regsAlt = this.regsAltStack = [];
|
||||
this.regsPAR = this.regsPDR = this.regsUniMap = this.regsControl = [];
|
||||
this.opFlags = 0;
|
||||
|
||||
/*
|
||||
* These properties will be initialized by initMMU()
|
||||
*/
|
||||
this.regMMR0 = this.regMMR1 = this.regMMR2 = this.regMMR3 = 0;
|
||||
this.regErr = this.regPIR = this.regSLR = 0;
|
||||
this.regErr = this.regMBR = this.regPIR = this.regSLR = 0;
|
||||
this.mmuEnable = this.mmuLastMode = this.mmuLastPage = this.mmuMask = 0;
|
||||
this.addrLast = this.opLast = this.addrInvalid = 0;
|
||||
|
||||
this.mapMMR3 = [4,2,0,1]; // map from mode to MMR3 I/D bit
|
||||
|
||||
/*
|
||||
* Initialize processor operation to match the requested model.
|
||||
*
|
||||
|
|
@ -167,6 +164,7 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
}
|
||||
|
||||
this.nDisableTraps = 0;
|
||||
this.trapVector = this.trapReason = 0;
|
||||
|
||||
/** @type {IRQ|null} */
|
||||
this.irqNext = null; // the head of the active IRQ list, in priority order
|
||||
|
|
@ -174,8 +172,6 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
/** @type {Array.<IRQ>} */
|
||||
this.aIRQs = []; // list of all IRQs, active or not (to be used for auto-configuration)
|
||||
|
||||
this.flags.complete = false;
|
||||
|
||||
this.getByte = this.getByteDirect = this.getByteChecked;
|
||||
this.getWord = this.getWordDirect = this.getWordChecked;
|
||||
this.setByte = this.setByteDirect = this.setByteChecked;
|
||||
|
|
@ -187,7 +183,10 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
this.readWord = this.readWordFromVirtual;
|
||||
this.writeWord = this.writeWordToVirtual;
|
||||
|
||||
this.trapVector = this.trapReason = 0;
|
||||
this.srcMode = this.srcReg = 0;
|
||||
this.dstMode = this.dstReg = this.dstAddr = 0;
|
||||
|
||||
this.flags.complete = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -271,36 +270,37 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
this.flagZ = f; // PSW Z bit (TODO: Why do we clear instead of set Z, like other flags?)
|
||||
this.flagN = 0x8000; // PSW N bit
|
||||
this.regPSW = 0x000f; // PSW other bits (TODO: What's the point of setting the flag bits here, too?)
|
||||
|
||||
this.regsGen = [ // General R0-R7
|
||||
0, 0, 0, 0, 0, 0, 0, this.addrReset, -1, -2, -3, -4, -5, -6, -7, -8
|
||||
];
|
||||
|
||||
this.regsAlt = [ // Alternate R0-R5
|
||||
0, 0, 0, 0, 0, 0
|
||||
];
|
||||
this.regsAltStack = [ // Alternate R6 stack pointers (KERNEL, SUPER, UNUSED, USER)
|
||||
0, 0, 0, 0
|
||||
];
|
||||
this.pswMode = 0; // current memory management mode (see PDP11.MODE.KERNEL | SUPER | UNUSED | USER)
|
||||
this.mapMMR3 = [4,2,0,1]; // map from mode to MMR3 I/D bit
|
||||
this.mmuPDR = [ // memory management PDR registers by mode
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // KERNEL (8 KIPDR regs followed by 8 KDPDR regs)
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // SUPER (8 SIPDR regs followed by 8 SDPDR regs)
|
||||
[f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f], // mode 2 (not used)
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] // USER (8 UIPDR regs followed by 8 UDPDR regs)
|
||||
];
|
||||
this.mmuPAR = [ // memory management PAR registers by mode
|
||||
this.regsPAR = [ // memory management PAR registers by mode
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // KERNEL (8 KIPAR regs followed by 8 KDPAR regs)
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // SUPER (8 SIPDR regs followed by 8 SDPDR regs)
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // mode 2 (not used)
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] // USER (8 UIPDR regs followed by 8 UDPDR regs)
|
||||
];
|
||||
this.regsPDR = [ // memory management PDR registers by mode
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // KERNEL (8 KIPDR regs followed by 8 KDPDR regs)
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // SUPER (8 SIPDR regs followed by 8 SDPDR regs)
|
||||
[f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f], // mode 2 (not used)
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] // USER (8 UIPDR regs followed by 8 UDPDR regs)
|
||||
];
|
||||
this.regsUniMap = [ // 32 UNIBUS map registers
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
];
|
||||
this.regsControl = [ // various control registers (177740-177756) we don't really care about
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
];
|
||||
|
||||
this.pswMode = 0; // current memory management mode (see PDP11.MODE.KERNEL | SUPER | UNUSED | USER)
|
||||
this.pswTrap = -1;
|
||||
this.regMBR = 0;
|
||||
|
||||
/*
|
||||
|
|
@ -317,8 +317,6 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
this.srcMode = this.srcReg = 0;
|
||||
this.dstMode = this.dstReg = this.dstAddr = 0;
|
||||
|
||||
this.pswTrap = -1;
|
||||
|
||||
this.initMMU();
|
||||
}
|
||||
|
||||
|
|
@ -358,7 +356,7 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
/*
|
||||
* This stores the PC in the lower 16 bits, and any auto-incs or auto-decs from the last opcode in the
|
||||
* upper 16 bits; the lower 16 bits are used to update MMR2, and the upper 16 bits are used to update MMR1.
|
||||
* The upper bits are automatically zeroed at the start of every operation when PC is copied to opLast.
|
||||
* The upper bits are automatically zeroed at the start of every operation when the PC is copied to opLast.
|
||||
*/
|
||||
this.opLast = 0;
|
||||
|
||||
|
|
@ -639,30 +637,33 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
this.regsGen,
|
||||
this.regsAlt,
|
||||
this.regsAltStack,
|
||||
this.regsPAR,
|
||||
this.regsPDR,
|
||||
this.regsUniMap,
|
||||
this.regsControl,
|
||||
this.regErr,
|
||||
this.regMBR,
|
||||
this.regPIR,
|
||||
this.regSLR,
|
||||
this.pswTrap,
|
||||
this.pswMode,
|
||||
this.opFlags,
|
||||
this.regMMR0,
|
||||
this.regMMR1,
|
||||
this.regMMR2,
|
||||
this.regMMR3,
|
||||
this.mmuEnable,
|
||||
this.mmuLastMode,
|
||||
this.mmuLastPage,
|
||||
this.mmuPDR,
|
||||
this.mmuPAR,
|
||||
this.mmuEnable,
|
||||
this.mmuMask,
|
||||
this.addrLast,
|
||||
this.opLast
|
||||
this.opFlags,
|
||||
this.opLast,
|
||||
this.pswTrap,
|
||||
this.trapReason,
|
||||
this.trapVector
|
||||
]);
|
||||
state.set(1, [this.getPSW()]);
|
||||
state.set(2, [this.nTotalCycles, this.getSpeed()]);
|
||||
state.set(2, [this.nTotalCycles, this.getSpeed(), this.flags.autoStart]);
|
||||
state.set(3, this.saveIRQs());
|
||||
state.set(4, this.saveTimers());
|
||||
return state.data();
|
||||
}
|
||||
|
||||
|
|
@ -675,45 +676,48 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
*/
|
||||
restore(data)
|
||||
{
|
||||
var a;
|
||||
/*
|
||||
* ES6 ALERT: Gotta love these destructuring assignments, which make it easy to perform the inverse
|
||||
* of what save() does when it collects a bunch of object properties into an array.
|
||||
* ES6 ALERT: Gotta love these destructuring assignments, which make it easy to perform the
|
||||
* inverse of what save() does when it collects a bunch of object properties into an array.
|
||||
*/
|
||||
[
|
||||
this.regsGen,
|
||||
this.regsAlt,
|
||||
this.regsAltStack,
|
||||
this.regsPAR,
|
||||
this.regsPDR,
|
||||
this.regsUniMap,
|
||||
this.regsControl,
|
||||
this.regErr,
|
||||
this.regMBR,
|
||||
this.regPIR,
|
||||
this.regSLR,
|
||||
this.pswTrap,
|
||||
this.pswMode,
|
||||
this.opFlags,
|
||||
this.regMMR0,
|
||||
this.regMMR1,
|
||||
this.regMMR2,
|
||||
this.regMMR3,
|
||||
this.mmuEnable,
|
||||
this.mmuLastMode,
|
||||
this.mmuLastPage,
|
||||
this.mmuPDR,
|
||||
this.mmuPAR,
|
||||
this.mmuEnable,
|
||||
this.mmuMask,
|
||||
this.addrLast,
|
||||
this.opLast
|
||||
this.opFlags,
|
||||
this.opLast,
|
||||
this.pswTrap,
|
||||
this.trapReason,
|
||||
this.trapVector
|
||||
] = data[0];
|
||||
|
||||
a = data[1];
|
||||
var a = data[1];
|
||||
this.setPSW(a[0]);
|
||||
|
||||
a = data[2];
|
||||
this.nTotalCycles = a[0];
|
||||
this.setSpeed(a[1]);
|
||||
this.flags.autoStart = a[2];
|
||||
|
||||
this.restoreIRQs(data[3]);
|
||||
this.restoreTimers(data[4]);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -985,8 +989,7 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
*/
|
||||
addIRQ(vector, priority, message)
|
||||
{
|
||||
var irq = {vector: vector, priority: priority, message: message || 0, next: null};
|
||||
irq.name = PDP11.VECTORS[vector];
|
||||
var irq = {vector: vector, priority: priority, message: message || 0, name: PDP11.VECTORS[vector], next: null};
|
||||
this.aIRQs.push(irq);
|
||||
return irq;
|
||||
}
|
||||
|
|
@ -1087,6 +1090,22 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* findIRQ(vector)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} vector
|
||||
* @return {IRQ|null}
|
||||
*/
|
||||
findIRQ(vector)
|
||||
{
|
||||
for (var i = 0; i < this.aIRQs.length; i++) {
|
||||
var irq = this.aIRQs[i];
|
||||
if (irq.vector === vector) return irq;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* checkIRQs(priority)
|
||||
*
|
||||
|
|
@ -1109,6 +1128,41 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
this.irqNext = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* saveIRQs()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @return {Array.<number>}
|
||||
*/
|
||||
saveIRQs()
|
||||
{
|
||||
var aIRQVectors = [];
|
||||
var irq = this.irqNext;
|
||||
while (irq) {
|
||||
aIRQVectors.push(irq.vector);
|
||||
irq = irq.next;
|
||||
}
|
||||
return aIRQVectors;
|
||||
}
|
||||
|
||||
/**
|
||||
* restoreIRQs(aIRQVectors)
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {Array.<number>} aIRQVectors
|
||||
*/
|
||||
restoreIRQs(aIRQVectors)
|
||||
{
|
||||
for (var i = aIRQVectors.length - 1; i >= 0; i--) {
|
||||
var irq = this.findIRQ(aIRQVectors[i]);
|
||||
this.assert(irq != null);
|
||||
if (irq) {
|
||||
irq.next = this.irqNext;
|
||||
this.irqNext = irq;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* checkInterrupts()
|
||||
*
|
||||
|
|
@ -1615,8 +1669,8 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
* These next properties (in conjunction with setting PDP11.OPFLAG.TRAP_LAST) are purely an aid for the Debugger;
|
||||
* see getTrapStatus().
|
||||
*/
|
||||
this.trapVector = vector;
|
||||
this.trapReason = reason;
|
||||
this.trapVector = vector;
|
||||
|
||||
if (reason == PDP11.REASON.PANIC) {
|
||||
this.stopCPU();
|
||||
|
|
@ -1757,9 +1811,9 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
var page = addr >> 13;
|
||||
if (page > 7) mode |= 1;
|
||||
if (!(this.regMMR3 & this.mapMMR3[this.pswMode])) page &= 7;
|
||||
var pdr = this.mmuPDR[this.pswMode][page];
|
||||
var pdr = this.regsPDR[this.pswMode][page];
|
||||
var off = addr & 0x1fff;
|
||||
var paf = (this.mmuPAR[this.pswMode][page] << 6);
|
||||
var paf = (this.regsPAR[this.pswMode][page] << 6);
|
||||
addrPhysical = (paf + off) & this.mmuMask;
|
||||
if (addrPhysical >= BusPDP11.UNIBUS_22BIT) addrPhysical = this.mapUnibus(addrPhysical);
|
||||
a.push(addrPhysical); // a[0]
|
||||
|
|
@ -1838,8 +1892,8 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
|
||||
page = addrVirtual >> 13;
|
||||
if (!(this.regMMR3 & this.mapMMR3[this.pswMode])) page &= 7;
|
||||
pdr = this.mmuPDR[this.pswMode][page];
|
||||
addr = ((this.mmuPAR[this.pswMode][page] << 6) + (addrVirtual & 0x1fff)) & this.mmuMask;
|
||||
pdr = this.regsPDR[this.pswMode][page];
|
||||
addr = ((this.regsPAR[this.pswMode][page] << 6) + (addrVirtual & 0x1fff)) & this.mmuMask;
|
||||
|
||||
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.mapUnibus(addr);
|
||||
|
||||
|
|
@ -1928,7 +1982,7 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
/*
|
||||
* Aborts and traps: log FIRST trap and MOST RECENT abort
|
||||
*/
|
||||
this.mmuPDR[this.pswMode][page] = pdr;
|
||||
this.regsPDR[this.pswMode][page] = pdr;
|
||||
if (addr != ((BusPDP11.IOPAGE_22BIT | PDP11.UNIBUS.MMR0) & this.mmuMask) || this.pswMode) {
|
||||
this.mmuLastMode = this.pswMode;
|
||||
this.mmuLastPage = page;
|
||||
|
|
@ -2843,9 +2897,11 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
|
||||
if (!mode) {
|
||||
this.regsGen[reg] = (data = data < 0? this.regsGen[-data-1] : data);
|
||||
//noinspection JSUnresolvedFunction
|
||||
fnFlags.call(this, data);
|
||||
} else {
|
||||
var addr = this.getAddr(mode, reg, PDP11.ACCESS.WRITE_WORD);
|
||||
//noinspection JSUnresolvedFunction
|
||||
fnFlags.call(this, (data = data < 0? this.regsGen[-data-1] : data));
|
||||
this.setWord(addr, data);
|
||||
}
|
||||
|
|
@ -2974,7 +3030,7 @@ class CPUStatePDP11 extends CPUPDP11 {
|
|||
|
||||
} while (this.nStepCycles > 0);
|
||||
|
||||
return (this.flags.complete? this.nBurstCycles - this.nStepCycles : (this.flags.complete === undefined? 0 : -1));
|
||||
return (this.flags.complete? this.nBurstCycles - this.nStepCycles : (this.flags.complete === false? -1 : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1270,8 +1270,8 @@ class DebuggerPDP11 extends Debugger {
|
|||
|
||||
// this.println(data? "resuming" : "powering up");
|
||||
|
||||
if (data && this.restore) {
|
||||
if (!this.restore(data)) return false;
|
||||
if (data) {
|
||||
return this.restore(data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -1593,7 +1593,7 @@ class DebuggerPDP11 extends Debugger {
|
|||
checkMemoryRead(addr, nb)
|
||||
{
|
||||
if (this.checkBreakpoint(addr, nb || 1, this.aBreakRead)) {
|
||||
this.stopCPU(true);
|
||||
this.stopCPU(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -1618,7 +1618,7 @@ class DebuggerPDP11 extends Debugger {
|
|||
checkMemoryWrite(addr, nb)
|
||||
{
|
||||
if (this.checkBreakpoint(addr, nb || 1, this.aBreakWrite)) {
|
||||
this.stopCPU(true);
|
||||
this.stopCPU(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ if (NODE) {
|
|||
var Str = require("../../shared/es6/strlib");
|
||||
var Web = require("../../shared/es6/weblib");
|
||||
var Component = require("../../shared/es6/component");
|
||||
var State = require("../../shared/es6/state");
|
||||
var PDP11 = require("./defines");
|
||||
var BusPDP11 = require("./bus");
|
||||
var MemoryPDP11 = require("./memory");
|
||||
|
|
@ -62,7 +63,7 @@ class DevicePDP11 extends Component {
|
|||
super("Device", parmsDevice, DevicePDP11, MessagesPDP11.DEVICE);
|
||||
|
||||
this.kw11 = { // KW11 registers
|
||||
csr: 0,
|
||||
lks: PDP11.KW11.LKS.MON,
|
||||
timer: -1 // initBus() will initialize this timer ID
|
||||
};
|
||||
}
|
||||
|
|
@ -111,18 +112,18 @@ class DevicePDP11 extends Component {
|
|||
{
|
||||
if (DEBUGGER) {
|
||||
var cpu = this.cpu;
|
||||
this.dumpRegs("KIPDR", cpu.mmuPDR[0], 0, asArgs[0]);
|
||||
this.dumpRegs("KDPDR", cpu.mmuPDR[0], 8, asArgs[0]);
|
||||
this.dumpRegs("KIPAR", cpu.mmuPAR[0], 0, asArgs[0]);
|
||||
this.dumpRegs("KDPAR", cpu.mmuPAR[0], 8, asArgs[0], true);
|
||||
this.dumpRegs("SIPDR", cpu.mmuPDR[1], 0, asArgs[0]);
|
||||
this.dumpRegs("SDPDR", cpu.mmuPDR[1], 8, asArgs[0]);
|
||||
this.dumpRegs("SIPAR", cpu.mmuPAR[1], 0, asArgs[0]);
|
||||
this.dumpRegs("SDPAR", cpu.mmuPAR[1], 8, asArgs[0], true);
|
||||
this.dumpRegs("UIPDR", cpu.mmuPDR[3], 0, asArgs[0]);
|
||||
this.dumpRegs("UDPDR", cpu.mmuPDR[3], 8, asArgs[0]);
|
||||
this.dumpRegs("UIPAR", cpu.mmuPAR[3], 0, asArgs[0]);
|
||||
this.dumpRegs("UDPAR", cpu.mmuPAR[3], 8, asArgs[0], true);
|
||||
this.dumpRegs("KIPDR", cpu.regsPDR[0], 0, asArgs[0]);
|
||||
this.dumpRegs("KDPDR", cpu.regsPDR[0], 8, asArgs[0]);
|
||||
this.dumpRegs("KIPAR", cpu.regsPAR[0], 0, asArgs[0]);
|
||||
this.dumpRegs("KDPAR", cpu.regsPAR[0], 8, asArgs[0], true);
|
||||
this.dumpRegs("SIPDR", cpu.regsPDR[1], 0, asArgs[0]);
|
||||
this.dumpRegs("SDPDR", cpu.regsPDR[1], 8, asArgs[0]);
|
||||
this.dumpRegs("SIPAR", cpu.regsPAR[1], 0, asArgs[0]);
|
||||
this.dumpRegs("SDPAR", cpu.regsPAR[1], 8, asArgs[0], true);
|
||||
this.dumpRegs("UIPDR", cpu.regsPDR[3], 0, asArgs[0]);
|
||||
this.dumpRegs("UDPDR", cpu.regsPDR[3], 8, asArgs[0]);
|
||||
this.dumpRegs("UIPAR", cpu.regsPAR[3], 0, asArgs[0]);
|
||||
this.dumpRegs("UDPAR", cpu.regsPAR[3], 8, asArgs[0], true);
|
||||
if (cpu.regMMR3 & PDP11.MMR3.UNIBUS_MAP) {
|
||||
this.dumpRegs("UNIMAP", cpu.regsUniMap, -1, asArgs[0]);
|
||||
}
|
||||
|
|
@ -167,6 +168,39 @@ class DevicePDP11 extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* powerUp(data, fRepower)
|
||||
*
|
||||
* @this {DevicePDP11}
|
||||
* @param {Object|null} data
|
||||
* @param {boolean} [fRepower]
|
||||
* @return {boolean} true if successful, false if failure
|
||||
*/
|
||||
powerUp(data, fRepower)
|
||||
{
|
||||
if (!fRepower) {
|
||||
if (!data) {
|
||||
this.reset();
|
||||
} else {
|
||||
if (!this.restore(data)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* powerDown(fSave, fShutdown)
|
||||
*
|
||||
* @this {DevicePDP11}
|
||||
* @param {boolean} [fSave]
|
||||
* @param {boolean} [fShutdown]
|
||||
* @return {Object|boolean} component state if fSave; otherwise, true if successful, false if failure
|
||||
*/
|
||||
powerDown(fSave, fShutdown)
|
||||
{
|
||||
return fSave? this.save() : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* reset()
|
||||
*
|
||||
|
|
@ -178,6 +212,45 @@ class DevicePDP11 extends Component {
|
|||
this.cpu.setTimer(this.kw11.timer, 1000/60, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* save()
|
||||
*
|
||||
* This implements save support for the DevicePDP11 component.
|
||||
*
|
||||
* @this {DevicePDP11}
|
||||
* @return {Object}
|
||||
*/
|
||||
save()
|
||||
{
|
||||
var state = new State(this);
|
||||
state.set(0, [
|
||||
this.kw11.lks
|
||||
]);
|
||||
return state.data();
|
||||
}
|
||||
|
||||
/**
|
||||
* restore(data)
|
||||
*
|
||||
* This implements restore support for the DevicePDP11 component.
|
||||
*
|
||||
* @this {DevicePDP11}
|
||||
* @param {Object} data
|
||||
* @return {boolean} true if successful, false if failure
|
||||
*/
|
||||
restore(data)
|
||||
{
|
||||
/*
|
||||
* ES6 ALERT: Gotta love these destructuring assignments, which make it easy to perform the
|
||||
* inverse of what save() does when it collects a bunch of object properties into an array.
|
||||
*/
|
||||
[
|
||||
this.kw11.lks
|
||||
] = data[0];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* interruptKW11()
|
||||
*
|
||||
|
|
@ -350,7 +423,7 @@ class DevicePDP11 extends Component {
|
|||
readSIPDR(addr)
|
||||
{
|
||||
var reg = (addr >> 1) & 7;
|
||||
return this.cpu.mmuPDR[1][reg];
|
||||
return this.cpu.regsPDR[1][reg];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -363,7 +436,7 @@ class DevicePDP11 extends Component {
|
|||
writeSIPDR(data, addr)
|
||||
{
|
||||
var reg = (addr >> 1) & 7;
|
||||
this.cpu.mmuPDR[1][reg] = data & 0xff0f;
|
||||
this.cpu.regsPDR[1][reg] = data & 0xff0f;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -376,7 +449,7 @@ class DevicePDP11 extends Component {
|
|||
readSDPDR(addr)
|
||||
{
|
||||
var reg = ((addr >> 1) & 7) + 8;
|
||||
return this.cpu.mmuPDR[1][reg];
|
||||
return this.cpu.regsPDR[1][reg];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -389,7 +462,7 @@ class DevicePDP11 extends Component {
|
|||
writeSDPDR(data, addr)
|
||||
{
|
||||
var reg = ((addr >> 1) & 7) + 8;
|
||||
this.cpu.mmuPDR[1][reg] = data & 0xff0f;
|
||||
this.cpu.regsPDR[1][reg] = data & 0xff0f;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -402,7 +475,7 @@ class DevicePDP11 extends Component {
|
|||
readSIPAR(addr)
|
||||
{
|
||||
var reg = (addr >> 1) & 7;
|
||||
return this.cpu.mmuPAR[1][reg];
|
||||
return this.cpu.regsPAR[1][reg];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -415,8 +488,8 @@ class DevicePDP11 extends Component {
|
|||
writeSIPAR(data, addr)
|
||||
{
|
||||
var reg = (addr >> 1) & 7;
|
||||
this.cpu.mmuPAR[1][reg] = data;
|
||||
this.cpu.mmuPDR[1][reg] &= 0xff0f;
|
||||
this.cpu.regsPAR[1][reg] = data;
|
||||
this.cpu.regsPDR[1][reg] &= 0xff0f;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -430,7 +503,7 @@ class DevicePDP11 extends Component {
|
|||
readSDPAR(addr)
|
||||
{
|
||||
var reg = ((addr >> 1) & 7) + 8;
|
||||
return this.cpu.mmuPAR[1][reg];
|
||||
return this.cpu.regsPAR[1][reg];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -443,8 +516,8 @@ class DevicePDP11 extends Component {
|
|||
writeSDPAR(data, addr)
|
||||
{
|
||||
var reg = ((addr >> 1) & 7) + 8;
|
||||
this.cpu.mmuPAR[1][reg] = data;
|
||||
this.cpu.mmuPDR[1][reg] &= 0xff0f;
|
||||
this.cpu.regsPAR[1][reg] = data;
|
||||
this.cpu.regsPDR[1][reg] &= 0xff0f;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -457,7 +530,7 @@ class DevicePDP11 extends Component {
|
|||
readKIPDR(addr)
|
||||
{
|
||||
var reg = (addr >> 1) & 7;
|
||||
return this.cpu.mmuPDR[0][reg];
|
||||
return this.cpu.regsPDR[0][reg];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -470,7 +543,7 @@ class DevicePDP11 extends Component {
|
|||
writeKIPDR(data, addr)
|
||||
{
|
||||
var reg = (addr >> 1) & 7;
|
||||
this.cpu.mmuPDR[0][reg] = data & 0xff0f;
|
||||
this.cpu.regsPDR[0][reg] = data & 0xff0f;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -483,7 +556,7 @@ class DevicePDP11 extends Component {
|
|||
readKDPDR(addr)
|
||||
{
|
||||
var reg = ((addr >> 1) & 7) + 8;
|
||||
return this.cpu.mmuPDR[0][reg];
|
||||
return this.cpu.regsPDR[0][reg];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -496,7 +569,7 @@ class DevicePDP11 extends Component {
|
|||
writeKDPDR(data, addr)
|
||||
{
|
||||
var reg = ((addr >> 1) & 7) + 8;
|
||||
this.cpu.mmuPDR[0][reg] = data & 0xff0f;
|
||||
this.cpu.regsPDR[0][reg] = data & 0xff0f;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -509,7 +582,7 @@ class DevicePDP11 extends Component {
|
|||
readKIPAR(addr)
|
||||
{
|
||||
var reg = (addr >> 1) & 7;
|
||||
return this.cpu.mmuPAR[0][reg];
|
||||
return this.cpu.regsPAR[0][reg];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -522,8 +595,8 @@ class DevicePDP11 extends Component {
|
|||
writeKIPAR(data, addr)
|
||||
{
|
||||
var reg = (addr >> 1) & 7;
|
||||
this.cpu.mmuPAR[0][reg] = data;
|
||||
this.cpu.mmuPDR[0][reg] &= 0xff0f;
|
||||
this.cpu.regsPAR[0][reg] = data;
|
||||
this.cpu.regsPDR[0][reg] &= 0xff0f;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -537,7 +610,7 @@ class DevicePDP11 extends Component {
|
|||
readKDPAR(addr)
|
||||
{
|
||||
var reg = ((addr >> 1) & 7) + 8;
|
||||
return this.cpu.mmuPAR[0][reg];
|
||||
return this.cpu.regsPAR[0][reg];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -550,8 +623,8 @@ class DevicePDP11 extends Component {
|
|||
writeKDPAR(data, addr)
|
||||
{
|
||||
var reg = ((addr >> 1) & 7) + 8;
|
||||
this.cpu.mmuPAR[0][reg] = data;
|
||||
this.cpu.mmuPDR[0][reg] &= 0xff0f;
|
||||
this.cpu.regsPAR[0][reg] = data;
|
||||
this.cpu.regsPDR[0][reg] &= 0xff0f;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -564,7 +637,7 @@ class DevicePDP11 extends Component {
|
|||
readUIPDR(addr)
|
||||
{
|
||||
var reg = (addr >> 1) & 7;
|
||||
return this.cpu.mmuPDR[3][reg];
|
||||
return this.cpu.regsPDR[3][reg];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -577,7 +650,7 @@ class DevicePDP11 extends Component {
|
|||
writeUIPDR(data, addr)
|
||||
{
|
||||
var reg = (addr >> 1) & 7;
|
||||
this.cpu.mmuPDR[3][reg] = data & 0xff0f;
|
||||
this.cpu.regsPDR[3][reg] = data & 0xff0f;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -590,7 +663,7 @@ class DevicePDP11 extends Component {
|
|||
readUDPDR(addr)
|
||||
{
|
||||
var reg = ((addr >> 1) & 7) + 8;
|
||||
return this.cpu.mmuPDR[3][reg];
|
||||
return this.cpu.regsPDR[3][reg];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -603,7 +676,7 @@ class DevicePDP11 extends Component {
|
|||
writeUDPDR(data, addr)
|
||||
{
|
||||
var reg = ((addr >> 1) & 7) + 8;
|
||||
this.cpu.mmuPDR[3][reg] = data & 0xff0f;
|
||||
this.cpu.regsPDR[3][reg] = data & 0xff0f;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -616,7 +689,7 @@ class DevicePDP11 extends Component {
|
|||
readUIPAR(addr)
|
||||
{
|
||||
var reg = (addr >> 1) & 7;
|
||||
return this.cpu.mmuPAR[3][reg];
|
||||
return this.cpu.regsPAR[3][reg];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -629,8 +702,8 @@ class DevicePDP11 extends Component {
|
|||
writeUIPAR(data, addr)
|
||||
{
|
||||
var reg = (addr >> 1) & 7;
|
||||
this.cpu.mmuPAR[3][reg] = data;
|
||||
this.cpu.mmuPDR[3][reg] &= 0xff0f;
|
||||
this.cpu.regsPAR[3][reg] = data;
|
||||
this.cpu.regsPDR[3][reg] &= 0xff0f;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -644,7 +717,7 @@ class DevicePDP11 extends Component {
|
|||
readUDPAR(addr)
|
||||
{
|
||||
var reg = ((addr >> 1) & 7) + 8;
|
||||
return this.cpu.mmuPAR[3][reg];
|
||||
return this.cpu.regsPAR[3][reg];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -657,8 +730,8 @@ class DevicePDP11 extends Component {
|
|||
writeUDPAR(data, addr)
|
||||
{
|
||||
var reg = ((addr >> 1) & 7) + 8;
|
||||
this.cpu.mmuPAR[3][reg] = data;
|
||||
this.cpu.mmuPDR[3][reg] &= 0xff0f;
|
||||
this.cpu.regsPAR[3][reg] = data;
|
||||
this.cpu.regsPDR[3][reg] &= 0xff0f;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ class PC11 extends Component {
|
|||
powerUp(data, fRepower)
|
||||
{
|
||||
if (!fRepower) {
|
||||
if (!data || !this.restore) {
|
||||
if (!data) {
|
||||
this.reset();
|
||||
} else {
|
||||
if (!this.restore(data)) return false;
|
||||
|
|
|
|||
|
|
@ -361,7 +361,7 @@ class RK11 extends Component {
|
|||
powerUp(data, fRepower)
|
||||
{
|
||||
if (!fRepower) {
|
||||
if (!data || !this.restore) {
|
||||
if (!data) {
|
||||
this.reset();
|
||||
if (this.cmp.fReload) {
|
||||
/*
|
||||
|
|
@ -453,6 +453,8 @@ class RK11 extends Component {
|
|||
/**
|
||||
* saveController()
|
||||
*
|
||||
* TODO: Implement.
|
||||
*
|
||||
* @this {RK11}
|
||||
* @return {Array}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -392,7 +392,7 @@ class RL11 extends Component {
|
|||
powerUp(data, fRepower)
|
||||
{
|
||||
if (!fRepower) {
|
||||
if (!data || !this.restore) {
|
||||
if (!data) {
|
||||
this.reset();
|
||||
if (this.cmp.fReload) {
|
||||
/*
|
||||
|
|
@ -484,6 +484,8 @@ class RL11 extends Component {
|
|||
/**
|
||||
* saveController()
|
||||
*
|
||||
* TODO: Implement.
|
||||
*
|
||||
* @this {RL11}
|
||||
* @return {Array}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -423,7 +423,7 @@ class SerialPortPDP11 extends Component {
|
|||
*/
|
||||
this.initConnection(this.fNullModem);
|
||||
|
||||
if (!data || !this.restore) {
|
||||
if (!data) {
|
||||
this.reset();
|
||||
} else {
|
||||
if (!this.restore(data)) return false;
|
||||
|
|
@ -503,6 +503,8 @@ class SerialPortPDP11 extends Component {
|
|||
/**
|
||||
* saveRegisters()
|
||||
*
|
||||
* TODO: Implement.
|
||||
*
|
||||
* @this {SerialPortPDP11}
|
||||
* @return {Array}
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue