Cleaned up interrupt handling, register initialization, MMU initialization, etc

This commit is contained in:
Jeff 2016-09-26 16:53:37 -07:00 • committed by Jeff Parsons
commit 3497466113
8 changed files with 1642 additions and 1620 deletions

View file

@ -1087,8 +1087,12 @@ CPUPDP11.prototype.runCPU = function(fUpdateFocus)
this.stepCPU(nCyclesPerBurst);
}
catch(exception) {
/*
* We assume that any numeric exception was explicitly thrown by the CPU to interrupt the
* current instruction (and by extension, the current burst, but not the current run). All
* other exceptions are re-thrown to the catch below, which will attempt a stack dump.
*/
if (typeof exception != "number") throw exception;
if (DEBUG) this.println("CPU exception: " + str.toHexWord(exception));
}
/*

View file

@ -89,6 +89,16 @@ function CPUStatePDP11(parmsCPU)
Component.subclass(CPUStatePDP11, CPUPDP11);
/**
* @typedef {{
* delay: number,
* priority: number,
* vector: number,
* callback: (function()|null|undefined)
* }} InterruptEvent
*/
var InterruptEvent;
/**
* initProcessor()
*
@ -139,21 +149,9 @@ CPUStatePDP11.prototype.initRegs = function()
this.regsAltStack = [ // Alternate R6 stack pointers (kernel, super, illegal, user)
0, 0, 0, 0
];
this.regSL = 0xff; // 177774
this.regPIR = 0; // 177772
this.regCPUErr = 0; // 177766
this.MMR0 = 0; // 177572
this.MMR1 = 0; // 177574
this.MMR2 = 0; // 177576
this.MMR3 = 0; // 172516
this.mmuMode = 0; // current memory management mode (see PDP11.MODE.KERNEL | SUPER | UNUSED | USER)
this.mmuEnable = 0; // MMU enabled for PDP11.ACCESS.READ or PDP11.ACCESS.WRITE
this.mmuLastMode = 0;
this.mmuLastPage = 0;
this.mmuLastVirtual = 0;
this.mmuMask = [ // mask to control I&D access for each mode
0x7, 0x7, 0x7, 0x7
];
this.mmuMap = [ // memory management register by mode - 16 PDR (8 I then 8 D descriptors) followed by 16 PAR (I/D addresses)
[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], // kernel
[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], // super
@ -167,18 +165,13 @@ CPUStatePDP11.prototype.initRegs = function()
this.controlReg = [ // various control registers we don't really care about
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
];
this.regOp = -1; // current opcode
this.opFlags = 0;
this.cpuType = 70;
this.trapPSW = -1;
this.interruptQueue = []; // List of interrupts pending
this.runState = 0; // 0=run, 1=step, 2=wait, 3=run
this.loopRate = 9999; // instructions we can execute in 12ms
this.priorityReview = 2; // flag to mark if we need to check priority change
this.initMemoryAccess();
this.resetRegs();
};
/**
@ -188,32 +181,31 @@ CPUStatePDP11.prototype.initRegs = function()
*/
CPUStatePDP11.prototype.resetRegs = function()
{
this.regSL = 0xff;
this.regCPUErr = 0;
this.interruptQueue = [];
this.regPIR = 0;
this.MMR0 = this.MMR1 = this.MMR2 = this.MMR3 = this.mmuFrozen = this.mmuEnable = 0;
this.mmuMask[0] = this.mmuMask[1] = this.mmuMask[3] = 0x7;
this.regSL = 0xff; // 177774
this.regErr = 0; // 177766
this.regPIR = 0; // 177772
this.MMR0 = 0; // 177572
this.MMR1 = 0; // 177574
this.MMR2 = 0; // 177576
this.MMR3 = 0; // 172516
this.mmuEnable = 0; // MMU enabled for PDP11.ACCESS.READ or PDP11.ACCESS.WRITE
this.mmuLastMode = 0;
this.mmuMask = [ // mask to control I&D access for each mode
0x7, 0x7, 0x7, 0x7
];
/**
* @type {Array.<InterruptEvent>}
*/
this.interruptQueue = []; // List of interrupts pending
this.priorityReview = 2; // flag to mark if we need to check priority change
this.initMemoryAccess();
};
/**
* initMemoryAccess()
*
* Define getAddr(), readWord(), etc, handlers appropriate for the current MMU mode.
*
* The initial goal is to eliminate unnecessary calls to mapVirtualToPhysical(); for example,
* readWordFromVirtual() always does this:
*
* return this.readWordFromPhysical(this.mapVirtualToPhysical(virtualAddress, PDP11.ACCESS.READ));
*
* and getAddrVirtual() -- formerly getAddrByMode() -- always does this:
*
* return this.mapVirtualToPhysical(this.getVirtualByMode(addressMode, accessFlags), accessFlags);
*
* So now we define readWord() and getAddr() functions that are more appropriate for the current MMU mode.
* Define getAddr(), readWord(), etc, handlers appropriate for the current MMU mode, in order to
* eliminate unnecessary calls to mapVirtualToPhysical().
*
* @this {CPUStatePDP11}
*/
@ -230,6 +222,42 @@ CPUStatePDP11.prototype.initMemoryAccess = function()
}
};
/**
* getMMR0()
*
* @this {CPUStatePDP11}
* @return {number}
*/
CPUStatePDP11.prototype.getMMR0 = function()
{
return (this.MMR0 & 0xf381) | (this.mmuLastMode << 5) | (this.mmuLastPage << 1);
};
/**
* setMMR0()
*
* @this {CPUStatePDP11}
* @param {number} newMMR0
* @return {number}
*/
CPUStatePDP11.prototype.setMMR0 = function(newMMR0)
{
this.MMR0 = newMMR0 &= 0xf381;
this.mmuLastMode = (newMMR0 >> 5) & 3;
this.mmuLastPage = (newMMR0 >> 1) & 0xf;
if (newMMR0 & 0x101) {
if (newMMR0 & 0x1) {
this.mmuEnable = PDP11.ACCESS.READ | PDP11.ACCESS.WRITE;
} else {
this.mmuEnable = PDP11.ACCESS.WRITE;
}
} else {
this.mmuEnable = 0;
}
this.initMemoryAccess();
return this.MMR0;
};
/**
* getChecksum()
*
@ -253,7 +281,7 @@ CPUStatePDP11.prototype.save = function()
{
var state = new State(this);
state.set(0, []);
state.set(1, [this.intFlags, this.nTotalCycles, this.getSpeed()]);
state.set(1, [this.nTotalCycles, this.getSpeed()]);
state.set(2, this.bus.saveMemory());
return state.data();
};
@ -270,7 +298,6 @@ CPUStatePDP11.prototype.save = function()
CPUStatePDP11.prototype.restore = function(data)
{
var a = data[1];
this.intFlags = a[0];
this.nTotalCycles = a[1];
this.setSpeed(a[3]);
return this.bus.restoreMemory(data[2]);
@ -499,45 +526,6 @@ CPUStatePDP11.prototype.getSP = function()
return this.regsGen[6];
};
/**
* checkINTR()
*
* @this {CPUStatePDP11}
* @return {boolean} true if execution may proceed, false if not
*/
CPUStatePDP11.prototype.checkINTR = function()
{
if (this.intFlags & PDP11.INTFLAG.HALT) {
/*
* As discussed in opHLT(), the CPU is never REALLY halted by a HLT instruction; instead, opHLT()
* calls requestHALT(), which sets INTFLAG.HALT and signals to stepCPU() that it's free to end the
* current burst AND that it should not execute any more instructions until checkINTR() indicates
* that a hardware interrupt has been requested.
*/
this.endBurst();
return false;
}
return true;
};
/**
* clearINTR(nLevel)
*
* Clear the corresponding interrupt level.
*
* nLevel can either be a valid interrupt level (0-7), or -1 to clear all pending interrupts
* (eg, in the event of a system-wide reset).
*
* @this {CPUStatePDP11}
* @param {number} nLevel (0-7, or -1 for all)
*/
CPUStatePDP11.prototype.clearINTR = function(nLevel)
{
var bitsClear = nLevel < 0? 0xff : (1 << nLevel);
this.intFlags &= ~bitsClear;
};
/**
* requestHALT()
*
@ -545,7 +533,7 @@ CPUStatePDP11.prototype.clearINTR = function(nLevel)
*/
CPUStatePDP11.prototype.requestHALT = function()
{
this.intFlags |= PDP11.INTFLAG.HALT;
// TODO: There will be more work to do than this....
this.endBurst();
};
@ -602,6 +590,50 @@ CPUStatePDP11.prototype.interrupt = function(delay, priority, vector, callback)
this.priorityReview = 2;
};
/**
* checkInterruptQueue()
*
* @this {CPUStatePDP11}
*/
CPUStatePDP11.prototype.checkInterruptQueue = function()
{
if (this.priorityReview == 1) {
this.priorityReview = 2; // SPL delay
} else {
this.priorityReview = 0;
var interruptEvent = null;
var savePSW = this.regPIR & 0xe0;
for (var i = this.interruptQueue.length; --i >= 0;) {
if (this.interruptQueue[i].delay > 0) {
this.interruptQueue[i].delay--;
this.priorityReview = 2;
break; // Decrement only one delay 'difference' per cycle
}
//if (typeof this.interruptQueue[i].callback !== "undefined") {
if (this.interruptQueue[i].callback) {
if (!this.interruptQueue[i].callback()) {
this.interruptQueue.splice(i, 1);
continue;
}
//delete
this.interruptQueue[i].callback = null;
}
if (this.interruptQueue[i].priority > savePSW) {
savePSW = this.interruptQueue[i].priority;
interruptEvent = this.interruptQueue[i];
this.interruptQueue.splice(i, 1);
}
}
if (savePSW > (this.PSW & 0xe0)) {
if (!interruptEvent) {
this.trap(PDP11.TRAP.PIRQ, 42);
} else {
this.trap(interruptEvent.vector, 44);
}
}
}
};
/**
* getPSW()
*
@ -752,7 +784,7 @@ CPUStatePDP11.prototype.panic = function(reason)
*
* @this {CPUStatePDP11}
* @param {number} vector
* @param {number} reason
* @param {number} [reason]
*/
CPUStatePDP11.prototype.trap = function(vector, reason)
{
@ -783,7 +815,7 @@ CPUStatePDP11.prototype.trap = function(vector, reason)
this.setPSW((newPSW & 0xcfff) | ((this.trapPSW >> 2) & 0x3000));
if (doubleTrap) {
this.regCPUErr |= PDP11.CPUERR.RED;
this.regErr |= PDP11.CPUERR.RED;
this.regsGen[6] = 4;
}
@ -793,7 +825,10 @@ CPUStatePDP11.prototype.trap = function(vector, reason)
this.opFlags &= ~PDP11.OPFLAG.TRAP_MASK; // lose interest in traps after an abort
this.trapPSW = -1; // reset flag that we have a trap within a trap
throw vector | (reason << 8);
if (DEBUG) this.println("trap to vector " + str.toOct(vector, 3) + (reason? " (reason " + reason + ")" : ""));
throw vector;
};
/**
@ -878,7 +913,7 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessFl
physicalAddress |= BusPDP11.IOPAGE_22BIT;
} else { // no max_memory check in 16 bit mode
if ((physicalAddress & 1) && !(accessFlags & PDP11.ACCESS.BYTE)) {
this.regCPUErr |= PDP11.CPUERR.ODDADDR;
this.regErr |= PDP11.CPUERR.ODDADDR;
this.trap(PDP11.TRAP.BUS_ERROR, 22);
}
}
@ -897,11 +932,11 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessFl
}
if (physicalAddress < BusPDP11.IOPAGE_UNIBUS) {
if (physicalAddress >= BusPDP11.MAX_MEMORY) {
this.regCPUErr |= PDP11.CPUERR.NOMEMORY;
this.regErr |= PDP11.CPUERR.NOMEMORY;
this.trap(PDP11.TRAP.BUS_ERROR, 24); // KB11-EM does this after ABORT handling - KB11-CM before
}
if ((physicalAddress & 1) && !(accessFlags & PDP11.ACCESS.BYTE)) {
this.regCPUErr |= PDP11.CPUERR.ODDADDR;
this.regErr |= PDP11.CPUERR.ODDADDR;
this.trap(PDP11.TRAP.BUS_ERROR, 26);
}
}
@ -1115,11 +1150,11 @@ CPUStatePDP11.prototype.pushWord = function(data)
if ((!this.mmuMode) && virtualAddress <= this.regSL && virtualAddress > 4) {
if (virtualAddress <= this.regSL - 32) {
this.regCPUErr |= PDP11.CPUERR.RED;
this.regErr |= PDP11.CPUERR.RED;
this.regsGen[6] = 4;
this.trap(PDP11.TRAP.BUS_ERROR, 32);
} else {
this.regCPUErr |= PDP11.CPUERR.YELLOW;
this.regErr |= PDP11.CPUERR.YELLOW;
this.opFlags |= 4;
}
}
@ -1179,11 +1214,11 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
if (reg === 6 && (!this.mmuMode) && (accessFlags & PDP11.ACCESS.WRITE) &&
(this.regsGen[6] <= this.regSL || this.regsGen[6] >= 0xfffe)) {
if (this.regsGen[6] <= this.regSL - 32 || this.regsGen[6] >= 0xfffe) {
this.regCPUErr |= PDP11.CPUERR.RED;
this.regErr |= PDP11.CPUERR.RED;
this.regsGen[6] = 4;
this.trap(PDP11.TRAP.BUS_ERROR, 36);
} else {
this.regCPUErr |= PDP11.CPUERR.YELLOW;
this.regErr |= PDP11.CPUERR.YELLOW;
this.opFlags |= PDP11.OPFLAG.TRAP_SP;
}
}
@ -1284,11 +1319,11 @@ CPUStatePDP11.prototype.getVirtualByMode = function(addressMode, accessFlags)
if (reg === 6 && (!this.mmuMode) && (accessFlags & PDP11.ACCESS.WRITE) && stepSize <= 0 && (this.regsGen[6] <= this.regSL || this.regsGen[6] >= 0xfffe)) {
if (this.regsGen[6] <= this.regSL - 32) {
this.regCPUErr |= PDP11.CPUERR.RED;
this.regErr |= PDP11.CPUERR.RED;
this.regsGen[6] = 4;
this.trap(PDP11.TRAP.BUS_ERROR, 38);
} else {
this.regCPUErr |= PDP11.CPUERR.YELLOW;
this.regErr |= PDP11.CPUERR.YELLOW;
this.opFlags |= PDP11.OPFLAG.TRAP_SP;
}
}
@ -1532,10 +1567,6 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
*/
this.nBurstCycles = this.nStepCycles = nMinCycles;
/*
* NOTE: If checkINTR() returns false, INTFLAG.HALT must be set, so no instructions should be executed.
*/
if (this.checkINTR()) {
do {
if (DEBUGGER && fDebugCheck) {
if (this.dbg.checkInstruction(this.getPC(), nDebugState)) {
@ -1545,13 +1576,6 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
nDebugState = 1;
}
var opCode,
src,
dst,
dstAddr,
result,
virtualAddress, savePSW, reg, i, j;
/*
* Check for any pending traps.
*
@ -1574,45 +1598,8 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
this.opFlags &= ~PDP11.OPFLAG.TRAP_MASK;
}
if (this.priorityReview) { // if nothing has changed don't check priority
if (this.priorityReview === 1) {
this.priorityReview = 2; // SPL delay
} else {
this.priorityReview = 0;
j = -1;
savePSW = this.regPIR & 0xe0;
if ((i = this.interruptQueue.length) > 0) {
while (i-- > 0) {
if (this.interruptQueue[i].delay > 0) {
this.interruptQueue[i].delay--;
this.priorityReview = 2;
break; // Decrement only one delay 'difference' per cycle
}
//if (typeof this.interruptQueue[i].callback !== "undefined") {
if (this.interruptQueue[i].callback) {
if (!this.interruptQueue[i].callback()) {
this.interruptQueue.splice(i, 1);
j--;
continue;
}
//delete
this.interruptQueue[i].callback = null;
}
if (this.interruptQueue[i].priority > savePSW) {
savePSW = this.interruptQueue[i].priority;
j = i;
}
}
}
if (savePSW > (this.PSW & 0xe0)) {
if (j < 0) {
this.trap(PDP11.TRAP.PIRQ, 42);
} else {
this.trap(this.interruptQueue[j].vector, 44);
this.interruptQueue.splice(j, 1);
}
}
}
if (this.priorityReview) {
this.checkInterruptQueue();
}
if (!(this.MMR0 & 0xe000)) {
@ -1632,7 +1619,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
* it to detect if our new decode() function has processed (ie, "consumed") the opcode,
* by setting it to -1. If it has, then we can skip the older opcode decode logic below.
*/
this.regOp = opCode = this.readWordFromVirtual(this.regsGen[7]);
var opCode = this.regOp = this.readWordFromVirtual(this.regsGen[7]);
if (opCode >= 0) this.regsGen[7] = (this.regsGen[7] + 2) & 0xffff;
this.decode(opCode);
@ -1643,6 +1630,13 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
break;
}
// var opCode,
// src,
// dst,
// dstAddr,
// result,
// virtualAddress, savePSW, reg, i, j;
switch (opCode & 0xF000) /*0170000*/ { // Double operand instructions xxSSDD
case 0x1000: /*0010000*/ // MOV 01SSDD
//LOG_INSTRUCTION(opCode, 2, "MOV");
@ -2619,7 +2613,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
// case 0x0: /*0000000*/ // HALT 000000
// //LOG_INSTRUCTION(opCode, 0, "HALT");
// if (0xc000 & this.PSW) {
// this.regCPUErr |= PDP11.CPUERR.BADHALT;
// this.regErr |= PDP11.CPUERR.BADHALT;
// this.trap(PDP11.TRAP.BUS_ERROR, 46);
// } else {
// this.runState = 3; // halt
@ -2695,7 +2689,6 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
// }
}
} while (this.nStepCycles > 0);
}
return (this.flags.complete? this.nBurstCycles - this.nStepCycles : (this.flags.complete === undefined? 0 : -1));
};

View file

@ -1200,12 +1200,14 @@ if (DEBUGGER) {
}
}
catch(exception) {
/*
* We assume that any numeric exception was explicitly thrown by the CPU to interrupt the
* current instruction. For all other exceptions, we attempt a stack dump.
*/
if (typeof exception != "number") {
var e = exception;
this.nCycles = 0;
this.cpu.setError(e.stack || e.message);
} else {
if (DEBUG) this.println("CPU exception: " + str.toHexWord(exception));
}
}
@ -1980,11 +1982,11 @@ if (DEBUGGER) {
}
else if (opTypeOther == DebuggerPDP11.OP_DSTNUM3) {
disp = (opCode & 0x7);
sOperand = this.toStrBase(disp, 2);
sOperand = this.toStrBase(disp, 1);
}
else if (opTypeOther == DebuggerPDP11.OP_DSTNUM6) {
disp = (opCode & 0x3f);
sOperand = this.toStrBase(disp);
sOperand = this.toStrBase(disp, 1);
}
else {
/*

View file

@ -157,14 +157,6 @@ var PDP11 = {
CMODE: 14
}
},
/*
* Interrupt-related flags (stored in intFlags)
*/
INTFLAG: {
NONE: 0x0000,
INTR: 0x00ff, // mask for 8 bits, representing interrupt levels 0-7
HALT: 0x0100 // halt requested; see opHLT()
},
/*
* Internal operation state flags
*/

View file

@ -233,6 +233,38 @@ DevicePDP11.prototype.writeLKS = function(data, addr)
this.kw11.lks = data & ~PDP11.KW11.LKS.MONITOR;
};
/**
* readMMR0(addr)
*
* @this {DevicePDP11}
* @param {number} addr (eg, PDP11.UNIBUS.MMR0 or 177572)
* @return {number}
*/
DevicePDP11.prototype.readMMR0 = function(addr)
{
return this.cpu.getMMR0();
};
/**
* writeMMR0(data, addr)
*
* @this {DevicePDP11}
* @param {number} data
* @param {number} addr (eg, PDP11.UNIBUS.MMR0 or 177572)
*/
DevicePDP11.prototype.writeMMR0 = function(data, addr)
{
/*
* Set idx to 1 (22-bit), 2 (18-bit), or 4 (16-bit)
*/
var idx = 4;
data = this.cpu.setMMR0(data);
if (data & PDP11.MMR0.ENABLED | PDP11.MMR0.DSTMODE) {
idx = (this.cpu.MMR3 & PDP11.MMR3.MMU_22BIT)? 1 : 2;
}
this.display.misc = (this.display.misc & ~7) | idx;
};
/**
* readXCSR(addr)
*
@ -890,24 +922,23 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
switch (physicalAddress & ~0x3F) /*077*/ {
case 0x3FFFC0: /*017777700*/ // 017777700 - 017777777
switch (physicalAddress & ~1) {
/*
* Superseded by UNIBUS_TABLE (more of this code will be commented out
* as it is replaced by read/write handlers in the UNIBUS_TABLE; stay tuned).
*
case 0x3FFFFE: // 017777776 // PSW
result = cpu.getPSW();
if (data >= 0) {
if (physicalAddress & 1) {
data = (data << 8) | (result & 0xff);
} else {
if (byteFlag) data = (result & 0xff00) | (data & 0xff);
}
data = (data & 0xf8ef) | (result & 0x0710);
cpu.setPSW(data);
return -1; // KLUDGE - no trap but abort any CC updates
}
break;
*/
//
// Superseded by UNIBUS_TABLE (more of this code will be commented out
// as it is replaced by read/write handlers in UNIBUS_TABLE; stay tuned).
//
// case 0x3FFFFE: // 017777776 // PSW
// result = cpu.getPSW();
// if (data >= 0) {
// if (physicalAddress & 1) {
// data = (data << 8) | (result & 0xff);
// } else {
// if (byteFlag) data = (result & 0xff00) | (data & 0xff);
// }
// data = (data & 0xf8ef) | (result & 0x0710);
// cpu.setPSW(data);
// return -1; // KLUDGE - no trap but abort any CC updates
// }
// break;
case 0x3FFFFC: /*017777774*/ // stack limit
if (data < 0) {
result = cpu.regSL & 0xff00;
@ -941,9 +972,9 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
case 0x3FFFF6: /*017777766*/ // CPU error
if (cpu.cpuType !== 70) return cpu.trap(PDP11.TRAP.BUS_ERROR, 222);
if (data < 0) {
result = cpu.regCPUErr;
result = cpu.regErr;
} else {
result = cpu.regCPUErr = 0; // TODO: Always writes as zero?
result = cpu.regErr = 0; // TODO: Always writes as zero?
}
break;
case 0x3FFFF4: /*017777764*/ // System I/D
@ -1038,7 +1069,7 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
}
return result;
default:
cpu.regCPUErr |= PDP11.CPUERR.TIMEOUT;
cpu.regErr |= PDP11.CPUERR.TIMEOUT;
return cpu.trap(PDP11.TRAP.BUS_ERROR, 124);
}
break;
@ -1062,32 +1093,32 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
result = cpu.MMR1;
if (result & 0xff00) result = ((result << 8) | (result >> 8)) & 0xffff;
break;
case 0x3FFF7A: /*017777572*/ // MMR0
cpu.MMR0 = (cpu.MMR0 & 0xf381) | (cpu.mmuLastMode << 5) | (cpu.mmuLastPage << 1);
if (data < 0) {
result = cpu.MMR0;
} else {
result = this.insertData(cpu.MMR0, physicalAddress, data, byteFlag);
if (result >= 0) {
cpu.MMR0 = result &= 0xf381;
cpu.mmuLastMode = (result >> 5) & 3;
cpu.mmuLastPage = (result >> 1) & 0xf;
if (result & 0x101) {
idx = 2; // 18 bit
if (cpu.MMR3 & 0x10) idx = 1; // 22 bit
if (result & 0x1) {
cpu.mmuEnable = PDP11.ACCESS.READ | PDP11.ACCESS.WRITE;
} else {
cpu.mmuEnable = PDP11.ACCESS.WRITE;
}
} else {
cpu.mmuEnable = 0;
idx = 4; // 16 bit
}
this.display.misc = (this.display.misc & ~7) | idx;
}
}
break;
// case 0x3FFF7A: /*017777572*/ // MMR0
// cpu.MMR0 = (cpu.MMR0 & 0xf381) | (cpu.mmuLastMode << 5) | (cpu.mmuLastPage << 1);
// if (data < 0) {
// result = cpu.MMR0;
// } else {
// result = this.insertData(cpu.MMR0, physicalAddress, data, byteFlag);
// if (result >= 0) {
// cpu.MMR0 = result &= 0xf381;
// cpu.mmuLastMode = (result >> 5) & 3;
// cpu.mmuLastPage = (result >> 1) & 0xf;
// if (result & 0x101) {
// idx = 2; // 18 bit
// if (cpu.MMR3 & 0x10) idx = 1; // 22 bit
// if (result & 0x1) {
// cpu.mmuEnable = PDP11.ACCESS.READ | PDP11.ACCESS.WRITE;
// } else {
// cpu.mmuEnable = PDP11.ACCESS.WRITE;
// }
// } else {
// cpu.mmuEnable = 0;
// idx = 4; // 16 bit
// }
// this.display.misc = (this.display.misc & ~7) | idx;
// }
// }
// break;
case 0x3FFF78: /*017777570*/ // console display/switch;
if (data < 0) {
result = this.display.switches & 0xffff;
@ -1191,7 +1222,7 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
// }
// break;
default:
cpu.regCPUErr |= PDP11.CPUERR.TIMEOUT;
cpu.regErr |= PDP11.CPUERR.TIMEOUT;
return cpu.trap(PDP11.TRAP.BUS_ERROR, 126);
}
break;
@ -1234,7 +1265,7 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
if (result >= 0) rk11.rkdb = result;
break;
default:
cpu.regCPUErr |= PDP11.CPUERR.TIMEOUT;
cpu.regErr |= PDP11.CPUERR.TIMEOUT;
return cpu.trap(PDP11.TRAP.BUS_ERROR, 128);
}
break;
@ -1339,7 +1370,7 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
if (result >= 0) rp11.rpcs3 = result;
break;
default:
cpu.regCPUErr |= PDP11.CPUERR.TIMEOUT;
cpu.regErr |= PDP11.CPUERR.TIMEOUT;
return cpu.trap(PDP11.TRAP.BUS_ERROR, 132);
}
break;
@ -1378,7 +1409,7 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
}
break;
default:
cpu.regCPUErr |= PDP11.CPUERR.TIMEOUT;
cpu.regErr |= PDP11.CPUERR.TIMEOUT;
return cpu.trap(PDP11.TRAP.BUS_ERROR, 134);
}
break;
@ -1404,7 +1435,7 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
}
break;
default:
cpu.regCPUErr |= PDP11.CPUERR.TIMEOUT;
cpu.regErr |= PDP11.CPUERR.TIMEOUT;
return cpu.trap(PDP11.TRAP.BUS_ERROR, 136);
}
break;
@ -1454,12 +1485,12 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
idx = (physicalAddress >> 1) & 0xff;
result = DevicePDP11.M9312[idx];
} else {
cpu.regCPUErr |= PDP11.CPUERR.TIMEOUT;
cpu.regErr |= PDP11.CPUERR.TIMEOUT;
return cpu.trap(PDP11.TRAP.BUS_ERROR, 138);
}
break;
default:
cpu.regCPUErr |= PDP11.CPUERR.TIMEOUT;
cpu.regErr |= PDP11.CPUERR.TIMEOUT;
return cpu.trap(PDP11.TRAP.BUS_ERROR, 142);
}
if (byteFlag && result >= 0) { // make any required byte adjustment
@ -1480,6 +1511,7 @@ DevicePDP11.prototype.access = function(physicalAddress, data, byteFlag)
*/
DevicePDP11.UNIBUS_TABLE = {
[PDP11.UNIBUS.LKS]: [null, null, DevicePDP11.prototype.readLKS, DevicePDP11.prototype.writeLKS],
[PDP11.UNIBUS.MMR0]: [null, null, DevicePDP11.prototype.readMMR0, DevicePDP11.prototype.writeMMR0],
[PDP11.UNIBUS.XCSR]: [null, null, DevicePDP11.prototype.readXCSR, DevicePDP11.prototype.writeXCSR],
[PDP11.UNIBUS.PSW]: [null, null, DevicePDP11.prototype.readPSW, DevicePDP11.prototype.writePSW]
};

View file

@ -659,25 +659,25 @@ if (DEBUGGER) {
};
/**
* toStrBase(n, cch)
* toStrBase(n, nBytes)
*
* Use this instead of str.toHex() or str.toOct() to convert words to the default base.
* Use this instead of str.toHex() or str.toOct() to convert bytes/words to the Debugger's default base.
*
* @this {Debugger}
* @param {number|null|undefined} n
* @param {number} [cch] is the desired number of hex digits (0 or undefined for default)
* @param {number} [nBytes] is the number of bytes to display, which we translate into a number of characters
* @return {string}
*/
Debugger.prototype.toStrBase = function(n, cch)
Debugger.prototype.toStrBase = function(n, nBytes)
{
switch(this.nBase) {
case 8:
return str.toOct(n, cch);
return str.toOct(n, nBytes * 3);
case 10:
return n.toString(); // TODO: Do we want to support any formatting based on cch?
return n.toString();
case 16:
default:
return str.toHex(n, cch);
return str.toHex(n, nBytes * 2);
}
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long