Enable the Debugger to get/set front panel switches as register SW
This commit is contained in:
parent
d5c7bf0b5d
commit
b3bf213cd9
8 changed files with 563 additions and 454 deletions
|
|
@ -266,6 +266,7 @@ if (DEBUGGER) {
|
|||
* Register numbers 0-7 are reserved for cpu.regsGen, 8-15 are reserved for cpu.regsAlt, and 16-19 for cpu.regsStack.
|
||||
*/
|
||||
DebuggerPDP11.REG_PSW = 20;
|
||||
DebuggerPDP11.REG_SW = 21;
|
||||
|
||||
/*
|
||||
* Operand type masks; anything that's not covered by OP_SRC or OP_DST must be a OP_OTHER value.
|
||||
|
|
@ -465,6 +466,7 @@ if (DEBUGGER) {
|
|||
this.bus = bus;
|
||||
this.cpu = cpu;
|
||||
this.cmp = cmp;
|
||||
this.panel = cmp.panel;
|
||||
|
||||
/*
|
||||
* Re-initialize Debugger message support if necessary
|
||||
|
|
@ -1125,6 +1127,9 @@ if (DEBUGGER) {
|
|||
case "PC":
|
||||
iReg = 7;
|
||||
break;
|
||||
case "SW":
|
||||
iReg = 21;
|
||||
break;
|
||||
default:
|
||||
if (sReg.charAt(0) == "R") {
|
||||
iReg = +sReg.charAt(1);
|
||||
|
|
@ -1139,7 +1144,7 @@ if (DEBUGGER) {
|
|||
* getRegName(iReg)
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
* @param {number} iReg
|
||||
* @param {number} iReg (0-7; not used for other registers)
|
||||
* @return {string}
|
||||
*/
|
||||
DebuggerPDP11.prototype.getRegName = function(iReg)
|
||||
|
|
@ -1151,7 +1156,7 @@ if (DEBUGGER) {
|
|||
* getRegValue(iReg)
|
||||
*
|
||||
* Register numbers 0-7 are reserved for cpu.regsGen, 8-15 are reserved for cpu.regsAlt,
|
||||
* 16-19 for cpu.regsAltStack, and 20 for regPSW.
|
||||
* 16-19 for cpu.regsAltStack, 20 for regPSW, and 21 for regSW.
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
* @param {number} iReg
|
||||
|
|
@ -1173,6 +1178,9 @@ if (DEBUGGER) {
|
|||
else if (iReg == DebuggerPDP11.REG_PSW) {
|
||||
value = this.cpu.getPSW();
|
||||
}
|
||||
else if (iReg == DebuggerPDP11.REG_SW && this.panel && this.panel.hasSwitches()) {
|
||||
value = this.panel.getSW();
|
||||
}
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
|
@ -1362,7 +1370,7 @@ if (DEBUGGER) {
|
|||
/*
|
||||
* Make an effort to keep any Front Panel in sync with us.
|
||||
*/
|
||||
if (this.cmp.panel && this.cmp.panel.stop) this.cmp.panel.stop();
|
||||
if (this.panel && this.panel.stop) this.panel.stop();
|
||||
this.cmp.updateStatus();
|
||||
}
|
||||
|
||||
|
|
@ -2390,6 +2398,9 @@ if (DEBUGGER) {
|
|||
else if (iReg == DebuggerPDP11.REG_PSW) {
|
||||
sReg = "PS=" + this.toStrBase(cpu.getPSW());
|
||||
}
|
||||
else if (iReg == DebuggerPDP11.REG_SW && this.panel && this.panel.hasSwitches()) {
|
||||
sReg = "SW=" + this.toStrBase(this.panel.getSW(), 3);
|
||||
}
|
||||
if (sReg) sReg += ' ';
|
||||
return sReg;
|
||||
};
|
||||
|
|
@ -2413,7 +2424,8 @@ if (DEBUGGER) {
|
|||
sDump += this.getRegOutput(i);
|
||||
}
|
||||
sDump += '\n';
|
||||
sDump += this.getRegOutput(PDP11.REG.SP) + this.getRegOutput(PDP11.REG.PC) + this.getRegOutput(DebuggerPDP11.REG_PSW);
|
||||
sDump += this.getRegOutput(PDP11.REG.SP) + this.getRegOutput(PDP11.REG.PC);
|
||||
sDump += this.getRegOutput(DebuggerPDP11.REG_PSW) + this.getRegOutput(DebuggerPDP11.REG_SW);
|
||||
sDump += this.getFlagOutput('T') + this.getFlagOutput('N') + this.getFlagOutput('Z') + this.getFlagOutput('V') + this.getFlagOutput('C');
|
||||
return sDump;
|
||||
};
|
||||
|
|
@ -3406,6 +3418,12 @@ if (DEBUGGER) {
|
|||
case "C":
|
||||
if (w) cpu.setCF(); else cpu.clearCF();
|
||||
break;
|
||||
case "SW":
|
||||
if (this.panel && this.panel.hasSwitches()) {
|
||||
this.panel.setSW(w);
|
||||
break;
|
||||
}
|
||||
/* falls through */
|
||||
default:
|
||||
if (sRegMatch.charAt(0) == 'R') {
|
||||
var iReg = +sRegMatch.charAt(1);
|
||||
|
|
@ -3666,7 +3684,7 @@ if (DEBUGGER) {
|
|||
* with displayLiveRegs enabled, so once the repeat count has been exhausted, we must
|
||||
* perform a final updateStatus().
|
||||
*/
|
||||
if (dbg.cmp.panel && dbg.cmp.panel.stop) dbg.cmp.panel.stop();
|
||||
if (dbg.panel && dbg.panel.stop) dbg.panel.stop();
|
||||
dbg.cmp.updateStatus();
|
||||
dbg.setBusy(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,30 +57,40 @@ function PanelPDP11(parmsPanel)
|
|||
|
||||
/*
|
||||
* If there are any live registers, LEDs, etc, to display, this will provide a count.
|
||||
*
|
||||
* TODO: Add some UI for fDisplayLiveRegs (either an XML property, or a UI checkbox, or both).
|
||||
*/
|
||||
this.cLiveRegs = 0;
|
||||
this.fDisplayLiveRegs = true;
|
||||
this.fLampTest = false;
|
||||
this.fExamine = this.fDeposit = false;
|
||||
|
||||
/*
|
||||
* regCNSW contains the Console (Front Panel) Switch Register, which is also available as a
|
||||
* regSwitches contains the Console (Front Panel) Switch Register, which is also available as a
|
||||
* read-only register at 177570 (but only the low 16 bits).
|
||||
*
|
||||
* regAddr is an internal register containing the contents of the Front Panel's ADDRESS display,
|
||||
* and regData corresponds to the DATA display. They are updated by setAddr() and setData(),
|
||||
* which in turn take care of calling setLEDArray().
|
||||
*/
|
||||
this.regCNSW = 0;
|
||||
this.regSwitches = 0;
|
||||
this.regAddr = this.regData = 0;
|
||||
this.regMisc = 0x14;
|
||||
|
||||
/*
|
||||
* The panel hardware has the following additional (supported) state; note that there are several
|
||||
* settings on a real Front Panel that we don't support (eg, stepping one cycle vs. one instruction).
|
||||
*
|
||||
* While my initial intent is to eventually support all the ADDRSEL switch settings, I probably
|
||||
* won't bother with any DATASEL switch settings; instead, I will automatically display the data
|
||||
* register (regData) [the equivalent of selecting 'DISPLAY REGISTER'] except when data is being
|
||||
* examined or deposited [the equivalent of selecting 'DATA PATHS'].
|
||||
*/
|
||||
this.fLampTest = false; // lamp (LED) test in progress
|
||||
this.fExamine = false; // true if the previously pressed switch was the 'EXAM' switch
|
||||
this.fDeposit = false; // true if the previously pressed switch was the 'DEP' switch
|
||||
this.nAddrSel = PanelPDP11.ADDRSEL.CONS_PHY;
|
||||
|
||||
/*
|
||||
* Every LED has a simple numeric value, assigned when setBinding() is called:
|
||||
*
|
||||
* 0 if off, 1 if on
|
||||
* zero if "off", non-zero if "on"
|
||||
*
|
||||
* initBus() will call displayLEDs() to ensure that every LED is set to its initial value.
|
||||
*/
|
||||
|
|
@ -122,6 +132,17 @@ function PanelPDP11(parmsPanel)
|
|||
|
||||
Component.subclass(PanelPDP11);
|
||||
|
||||
PanelPDP11.ADDRSEL = {
|
||||
KERNEL_I: 0, // use a 16-bit virtual address where bits 16 to 21 are always OFF
|
||||
KERNEL_D: 1, // use a 16-bit virtual address where bits 16 to 21 are always OFF
|
||||
SUPER_I: 2, // use a 16-bit virtual address where bits 16 to 21 are always OFF
|
||||
SUPER_D: 3, // use a 16-bit virtual address where bits 16 to 21 are always OFF
|
||||
USER_I: 4, // use a 16-bit virtual address where bits 16 to 21 are always OFF
|
||||
USER_D: 5, // use a 16-bit virtual address where bits 16 to 21 are always OFF
|
||||
PROG_PHY: 6, // display the 22-bit physical address of the current bus cycle generated by the MMU
|
||||
CONS_PHY: 7 // use a 22-bit physical address to perform console operations (e.g., LOAD ADRS, EXAM, & DEP)
|
||||
};
|
||||
|
||||
/*
|
||||
* To get the current state of a switch; eg::
|
||||
*
|
||||
|
|
@ -132,6 +153,7 @@ Component.subclass(PanelPDP11);
|
|||
* "step" behavior when pressed more than once in a row). Ditto for the LED table.
|
||||
*/
|
||||
PanelPDP11.SWITCH = {
|
||||
S0: 'S0',
|
||||
DEP: 'DEP',
|
||||
ENABLE: 'ENABLE',
|
||||
EXAM: 'EXAM',
|
||||
|
|
@ -144,6 +166,28 @@ PanelPDP11.LED = {
|
|||
B22: 'B22'
|
||||
};
|
||||
|
||||
/**
|
||||
* getSW()
|
||||
*
|
||||
* @this {PanelPDP11}
|
||||
* @return {number}
|
||||
*/
|
||||
PanelPDP11.prototype.getSW = function()
|
||||
{
|
||||
return this.regSwitches;
|
||||
};
|
||||
|
||||
/**
|
||||
* setSW(value)
|
||||
*
|
||||
* @this {PanelPDP11}
|
||||
* @param {number} value
|
||||
*/
|
||||
PanelPDP11.prototype.setSW = function(value)
|
||||
{
|
||||
this.setSwitches(value);
|
||||
};
|
||||
|
||||
/**
|
||||
* getSwitch(name)
|
||||
*
|
||||
|
|
@ -163,7 +207,6 @@ PanelPDP11.prototype.getSwitch = function(name)
|
|||
*/
|
||||
PanelPDP11.prototype.reset = function()
|
||||
{
|
||||
this.regMisc = (this.regMisc & ~0x77) | 0x14; // kernel 16 bit
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -639,7 +682,15 @@ PanelPDP11.prototype.processDeposit = function(value, index)
|
|||
if (this.fDeposit) {
|
||||
this.setAddr(this.regAddr + 2);
|
||||
}
|
||||
this.bus.setWordDirect(this.regAddr, this.setData(this.regCNSW));
|
||||
var w = this.setData(this.regSwitches);
|
||||
if (this.nAddrSel == PanelPDP11.ADDRSEL.CONS_PHY) {
|
||||
this.bus.setWordDirect(this.regAddr, w);
|
||||
} else {
|
||||
/*
|
||||
* TODO: This code is obviously incomplete, since it doesn't take into account the precise ADDRSEL mode.
|
||||
*/
|
||||
this.cpu.setWordDirect(this.regAddr, w);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -656,7 +707,16 @@ PanelPDP11.prototype.processExamine = function(value, index)
|
|||
if (this.fExamine) {
|
||||
this.setAddr(this.regAddr + 2);
|
||||
}
|
||||
this.setData(this.bus.getWordDirect(this.regAddr));
|
||||
var w;
|
||||
if (this.nAddrSel == PanelPDP11.ADDRSEL.CONS_PHY) {
|
||||
w = this.bus.getWordDirect(this.regAddr);
|
||||
} else {
|
||||
/*
|
||||
* TODO: This code is obviously incomplete, since it doesn't take into account the precise ADDRSEL mode.
|
||||
*/
|
||||
w = this.cpu.getWordDirect(this.regAddr);
|
||||
}
|
||||
this.setData(w);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -670,7 +730,7 @@ PanelPDP11.prototype.processExamine = function(value, index)
|
|||
PanelPDP11.prototype.processLoadAddr = function(value, index)
|
||||
{
|
||||
if (!value && !this.cpu.isRunning()) {
|
||||
this.setAddr(this.regCNSW);
|
||||
this.setAddr(this.regSwitches);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -696,9 +756,9 @@ PanelPDP11.prototype.processLampTest = function(value, index)
|
|||
PanelPDP11.prototype.processSwitchReg = function(value, index)
|
||||
{
|
||||
if (value) {
|
||||
this.regCNSW |= 1 << index;
|
||||
this.regSwitches |= 1 << index;
|
||||
} else {
|
||||
this.regCNSW &= ~(1 << index);
|
||||
this.regSwitches &= ~(1 << index);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -746,18 +806,46 @@ PanelPDP11.prototype.setLED = function(sBinding, value)
|
|||
};
|
||||
|
||||
/**
|
||||
* setLEDArray(sPrefix, data, nLEDs)
|
||||
* setLEDArray(sPrefix, value, nLEDs)
|
||||
*
|
||||
* @this {PanelPDP11}
|
||||
* @param {string} sPrefix
|
||||
* @param {number} data
|
||||
* @param {number} value
|
||||
* @param {number} nLEDs
|
||||
*/
|
||||
PanelPDP11.prototype.setLEDArray = function(sPrefix, data, nLEDs)
|
||||
PanelPDP11.prototype.setLEDArray = function(sPrefix, value, nLEDs)
|
||||
{
|
||||
for (var i = 0; i < nLEDs; i++) {
|
||||
var sBinding = sPrefix + i;
|
||||
this.setLED(sBinding, data & (1 << i));
|
||||
this.setLED(sBinding, value & (1 << i));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* hasSwitches(value)
|
||||
*
|
||||
* @this {PanelPDP11}
|
||||
* @return {boolean}
|
||||
*/
|
||||
PanelPDP11.prototype.hasSwitches = function()
|
||||
{
|
||||
return this.bindings[PanelPDP11.SWITCH.S0] !== undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* setSwitches(value)
|
||||
*
|
||||
* @this {PanelPDP11}
|
||||
* @param {number} value
|
||||
*/
|
||||
PanelPDP11.prototype.setSwitches = function(value)
|
||||
{
|
||||
if (this.hasSwitches()) {
|
||||
this.regSwitches = value;
|
||||
for (var i = 0; i < 22; i++) {
|
||||
this.switches['S'+i][0] = (value & (1 << i))? 1 : 0;
|
||||
}
|
||||
this.displaySwitches();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -817,7 +905,7 @@ PanelPDP11.prototype.updateStatus = function(fForce)
|
|||
* readCNSW(addr)
|
||||
*
|
||||
* If addr is set, then this a normal read, so we should return normal results (ie, switches);
|
||||
* if addr is NOT set, then this is a read-before-write, so we must return the value being updated (ie, data).
|
||||
* if addr is NOT set, then this is a read-before-write, so we must return the value being updated.
|
||||
*
|
||||
* @this {PanelPDP11}
|
||||
* @param {number} addr (eg, PDP11.UNIBUS.CNSW or 177570)
|
||||
|
|
@ -825,19 +913,19 @@ PanelPDP11.prototype.updateStatus = function(fForce)
|
|||
*/
|
||||
PanelPDP11.prototype.readCNSW = function(addr)
|
||||
{
|
||||
return (addr? this.regCNSW : this.regData) & 0xffff;
|
||||
return (addr? this.regSwitches : this.regData) & 0xffff;
|
||||
};
|
||||
|
||||
/**
|
||||
* writeCNSW(data, addr)
|
||||
* writeCNSW(value, addr)
|
||||
*
|
||||
* @this {PanelPDP11}
|
||||
* @param {number} data
|
||||
* @param {number} value
|
||||
* @param {number} addr (eg, PDP11.UNIBUS.CNSW or 177570)
|
||||
*/
|
||||
PanelPDP11.prototype.writeCNSW = function(data, addr)
|
||||
PanelPDP11.prototype.writeCNSW = function(value, addr)
|
||||
{
|
||||
this.regData = data;
|
||||
this.regData = value;
|
||||
};
|
||||
|
||||
PanelPDP11.UNIBUS_IOTABLE = {
|
||||
|
|
|
|||
|
|
@ -681,7 +681,7 @@ if (DEBUGGER) {
|
|||
var s;
|
||||
switch(this.nBase) {
|
||||
case 8:
|
||||
s = str.toOct(n, nBytes * 3);
|
||||
s = str.toOct(n, Math.round((8/3) * nBytes));
|
||||
break;
|
||||
case 10:
|
||||
s = n.toString();
|
||||
|
|
|
|||
Loading…
Reference in a new issue