Debugger improvements (dumping/setting MMU registers)
This commit is contained in:
parent
00d6fb6c59
commit
2b23c86649
8 changed files with 709 additions and 473 deletions
|
|
@ -243,17 +243,18 @@ CPUStatePDP11.prototype.resetCPU = function()
|
|||
*/
|
||||
CPUStatePDP11.prototype.resetMMU = function()
|
||||
{
|
||||
this.regSL = 0xff; // 177774
|
||||
this.regErr = 0; // 177766
|
||||
this.regPIR = 0; // 177772
|
||||
this.regMMR0 = 0; // 177572
|
||||
this.regMMR1 = 0; // 177574
|
||||
this.regMMR2 = 0; // 177576
|
||||
this.regMMR3 = 0; // 172516
|
||||
this.regErr = 0; // 177766
|
||||
this.regPIR = 0; // 177772
|
||||
this.regSL = 0xff; // 177774
|
||||
this.mmuEnable = 0; // MMU enabled for PDP11.ACCESS.READ or PDP11.ACCESS.WRITE
|
||||
this.mmuLastMode = 0;
|
||||
this.mmuMask = 0x3ffff;
|
||||
|
||||
this.lastAddr = 0; // this is queried by the Panel when it's not using its own ADDRESS register
|
||||
this.lastOp = 0; // stores the PC and any auto-incs or auto-decs from the last opcode; used to update MMR1 and MMR2
|
||||
|
||||
this.resetTriggers();
|
||||
|
|
@ -684,6 +685,17 @@ CPUStatePDP11.prototype.getPC = function()
|
|||
return this.regsGen[PDP11.REG.PC];
|
||||
};
|
||||
|
||||
/**
|
||||
* getLastAddr()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @return {number}
|
||||
*/
|
||||
CPUStatePDP11.prototype.getLastAddr = function()
|
||||
{
|
||||
return this.lastAddr;
|
||||
};
|
||||
|
||||
/**
|
||||
* getLastPC()
|
||||
*
|
||||
|
|
@ -1605,8 +1617,13 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessFl
|
|||
newMMR0 |= (this.mmuLastMode << 5) | (this.mmuLastPage << 1);
|
||||
this.assert(!(newMMR0 & ~PDP11.MMR0.UPDATE));
|
||||
this.setMMR0((this.regMMR0 & ~PDP11.MMR0.UPDATE) | newMMR0);
|
||||
/*
|
||||
* I've decided to NOT set fAbort if MMR0 already indicates an ABORT condition,
|
||||
* because otherwise we run the risk of infinitely looping; eg, we call trap(), which
|
||||
* calls mapVirtualToPhysical() on the trap vector, which faults again, etc.
|
||||
*/
|
||||
fAbort = true;
|
||||
}
|
||||
fAbort = true;
|
||||
}
|
||||
if (!(this.regMMR0 & (PDP11.MMR0.ABORT | PDP11.MMR0.TRAP_MMU))) {
|
||||
/*
|
||||
|
|
@ -1999,7 +2016,7 @@ CPUStatePDP11.prototype.getVirtualAddrByMode = function(mode, reg, accessFlags)
|
|||
*/
|
||||
CPUStatePDP11.prototype.readWordFromPhysical = function(physicalAddress)
|
||||
{
|
||||
return this.bus.getWord(physicalAddress);
|
||||
return this.bus.getWord(this.lastAddr = physicalAddress);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2013,7 +2030,7 @@ CPUStatePDP11.prototype.readWordFromPhysical = function(physicalAddress)
|
|||
*/
|
||||
CPUStatePDP11.prototype.readWordFromVirtual = function(virtualAddress)
|
||||
{
|
||||
return this.bus.getWord(this.mapVirtualToPhysical(virtualAddress, PDP11.ACCESS.READ_WORD));
|
||||
return this.bus.getWord(this.lastAddr = this.mapVirtualToPhysical(virtualAddress, PDP11.ACCESS.READ_WORD));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2027,7 +2044,7 @@ CPUStatePDP11.prototype.readWordFromVirtual = function(virtualAddress)
|
|||
*/
|
||||
CPUStatePDP11.prototype.writeWordToPhysical = function(physicalAddress, data)
|
||||
{
|
||||
this.bus.setWord(physicalAddress, data & 0xffff);
|
||||
this.bus.setWord(this.lastAddr = physicalAddress, data & 0xffff);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2041,7 +2058,7 @@ CPUStatePDP11.prototype.writeWordToPhysical = function(physicalAddress, data)
|
|||
*/
|
||||
CPUStatePDP11.prototype.writeWordToVirtual = function(virtualAddress, data)
|
||||
{
|
||||
this.bus.setWord(this.mapVirtualToPhysical(virtualAddress, PDP11.ACCESS.WRITE_WORD), data);
|
||||
this.bus.setWord(this.lastAddr = this.mapVirtualToPhysical(virtualAddress, PDP11.ACCESS.WRITE_WORD), data);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -266,7 +266,32 @@ 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_SR = 21; // SWITCH register; see Panel's getSR() and setSR()
|
||||
DebuggerPDP11.REG_PIR = 21;
|
||||
DebuggerPDP11.REG_ERR = 22;
|
||||
DebuggerPDP11.REG_SL = 23;
|
||||
DebuggerPDP11.REG_MMR0 = 24;
|
||||
DebuggerPDP11.REG_MMR1 = 25;
|
||||
DebuggerPDP11.REG_MMR2 = 26;
|
||||
DebuggerPDP11.REG_MMR3 = 27;
|
||||
DebuggerPDP11.REG_AR = 28; // ADDRESS register; see Panel's getAR() and setAR()
|
||||
DebuggerPDP11.REG_DR = 29; // DISPLAY/DATA register; see Panel's getDR() and setDR()
|
||||
DebuggerPDP11.REG_SR = 30; // SWITCH register; see Panel's getSR() and setSR()
|
||||
|
||||
DebuggerPDP11.REGS = {
|
||||
"SP": 6,
|
||||
"PC": 7,
|
||||
"PS": DebuggerPDP11.REG_PSW,
|
||||
"IR": DebuggerPDP11.REG_PIR,
|
||||
"ER": DebuggerPDP11.REG_ERR,
|
||||
"SL": DebuggerPDP11.REG_SL,
|
||||
"MMR0": DebuggerPDP11.REG_MMR0,
|
||||
"MMR1": DebuggerPDP11.REG_MMR1,
|
||||
"MMR2": DebuggerPDP11.REG_MMR2,
|
||||
"MMR3": DebuggerPDP11.REG_MMR3,
|
||||
"AR": DebuggerPDP11.REG_AR,
|
||||
"DR": DebuggerPDP11.REG_DR,
|
||||
"SR": DebuggerPDP11.REG_SR
|
||||
};
|
||||
|
||||
/*
|
||||
* Operand type masks; anything that's not covered by OP_SRC or OP_DST must be a OP_OTHER value.
|
||||
|
|
@ -1118,24 +1143,14 @@ if (DEBUGGER) {
|
|||
*/
|
||||
DebuggerPDP11.prototype.getRegIndex = function(sReg, off)
|
||||
{
|
||||
var iReg = -1;
|
||||
sReg = sReg.toUpperCase();
|
||||
switch(sReg) {
|
||||
case "SP":
|
||||
iReg = 6;
|
||||
break;
|
||||
case "PC":
|
||||
iReg = 7;
|
||||
break;
|
||||
case "SR":
|
||||
iReg = 21;
|
||||
break;
|
||||
default:
|
||||
var iReg = DebuggerPDP11.REGS[sReg];
|
||||
if (iReg == null) {
|
||||
iReg = -1;
|
||||
if (sReg.charAt(0) == "R") {
|
||||
iReg = +sReg.charAt(1);
|
||||
if (iReg < 0 || iReg > 7) iReg = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return iReg;
|
||||
};
|
||||
|
|
@ -1156,7 +1171,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, 20 for regPSW, and 21 for SR (SWITCH register).
|
||||
* 16-19 for cpu.regsAltStack, 20 for regPSW, etc.
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
* @param {number} iReg
|
||||
|
|
@ -1175,11 +1190,50 @@ if (DEBUGGER) {
|
|||
else if (iReg < 20) {
|
||||
value = this.cpu.regsAltStack[iReg-16];
|
||||
}
|
||||
else if (iReg == DebuggerPDP11.REG_PSW) {
|
||||
value = this.cpu.getPSW();
|
||||
}
|
||||
else if (iReg == DebuggerPDP11.REG_SR && this.panel && this.panel.hasSwitches()) {
|
||||
value = this.panel.getSR();
|
||||
else {
|
||||
var cpu = this.cpu;
|
||||
var panel = this.panel;
|
||||
switch(iReg) {
|
||||
case DebuggerPDP11.REG_PSW:
|
||||
value = this.cpu.getPSW();
|
||||
break;
|
||||
case DebuggerPDP11.REG_PIR:
|
||||
value = cpu.regPIR;
|
||||
break;
|
||||
case DebuggerPDP11.REG_ERR:
|
||||
value = cpu.regErr;
|
||||
break;
|
||||
case DebuggerPDP11.REG_SL:
|
||||
value = cpu.regSL;
|
||||
break;
|
||||
case DebuggerPDP11.REG_MMR0:
|
||||
value = panel.getMMR0();
|
||||
break;
|
||||
case DebuggerPDP11.REG_MMR1:
|
||||
value = panel.getMMR1();
|
||||
break;
|
||||
case DebuggerPDP11.REG_MMR2:
|
||||
value = panel.getMMR2();
|
||||
break;
|
||||
case DebuggerPDP11.REG_MMR3:
|
||||
value = panel.getMMR3();
|
||||
break;
|
||||
case DebuggerPDP11.REG_AR:
|
||||
if (panel) {
|
||||
value = panel.getAR();
|
||||
}
|
||||
break;
|
||||
case DebuggerPDP11.REG_DR:
|
||||
if (panel) {
|
||||
value = panel.getDR();
|
||||
}
|
||||
break;
|
||||
case DebuggerPDP11.REG_SR:
|
||||
if (panel && panel.hasSwitches()) {
|
||||
value = panel.getSR();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
|
|
@ -1371,6 +1425,7 @@ if (DEBUGGER) {
|
|||
* is calling us in a loop, in which case it will perform its own updateDisplays() when it's done.
|
||||
*/
|
||||
if (fUpdateDisplays !== false) {
|
||||
if (this.panel && this.panel.stop) this.panel.stop();
|
||||
this.cmp.updateDisplays(-1);
|
||||
}
|
||||
|
||||
|
|
@ -2393,28 +2448,86 @@ if (DEBUGGER) {
|
|||
else if (iReg >= 16 && iReg < 20) {
|
||||
sReg = "S" + (iReg - 16) + '=' + this.toStrBase(cpu.regsAltStack[iReg - 16]);
|
||||
}
|
||||
else if (iReg == DebuggerPDP11.REG_PSW) {
|
||||
sReg = "PS=" + this.toStrBase(cpu.getPSW());
|
||||
}
|
||||
else if (iReg == DebuggerPDP11.REG_SR && this.panel && this.panel.hasSwitches()) {
|
||||
sReg = "SR=" + this.toStrBase(this.panel.getSR(), 3);
|
||||
else {
|
||||
switch(iReg) {
|
||||
case DebuggerPDP11.REG_PSW:
|
||||
sReg = "PS=" + this.toStrBase(cpu.getPSW());
|
||||
break;
|
||||
case DebuggerPDP11.REG_PIR:
|
||||
sReg = "IR=" + this.toStrBase(cpu.regPIR);
|
||||
break;
|
||||
case DebuggerPDP11.REG_ERR:
|
||||
sReg = "ER=" + this.toStrBase(cpu.regErr);
|
||||
break;
|
||||
case DebuggerPDP11.REG_SL:
|
||||
sReg = "SL=" + this.toStrBase(cpu.regSL);
|
||||
break;
|
||||
case DebuggerPDP11.REG_MMR0:
|
||||
sReg = "MMR0=" + this.toStrBase(cpu.getMMR0());
|
||||
break;
|
||||
case DebuggerPDP11.REG_MMR1:
|
||||
sReg = "MMR1=" + this.toStrBase(cpu.getMMR1());
|
||||
break;
|
||||
case DebuggerPDP11.REG_MMR2:
|
||||
sReg = "MMR2=" + this.toStrBase(cpu.getMMR2());
|
||||
break;
|
||||
case DebuggerPDP11.REG_MMR3:
|
||||
sReg = "MMR3=" + this.toStrBase(cpu.getMMR3());
|
||||
break;
|
||||
case DebuggerPDP11.REG_AR:
|
||||
if (this.panel) {
|
||||
sReg = "AR=" + this.toStrBase(this.panel.getAR(), 3);
|
||||
}
|
||||
break;
|
||||
case DebuggerPDP11.REG_DR:
|
||||
if (this.panel) {
|
||||
sReg = "DR=" + this.toStrBase(this.panel.getDR());
|
||||
}
|
||||
break;
|
||||
case DebuggerPDP11.REG_SR:
|
||||
if (this.panel && this.panel.hasSwitches()) {
|
||||
sReg = "SR=" + this.toStrBase(this.panel.getSR(), 3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sReg) sReg += ' ';
|
||||
return sReg;
|
||||
};
|
||||
|
||||
/**
|
||||
* getRegDump()
|
||||
* getMiscDump()
|
||||
*
|
||||
* Sample register dump:
|
||||
*
|
||||
* R0=xxxx R1=xxxx R2=xxxx R3=xxxx R4=xxxx R5=xxxx
|
||||
* SP=xxxx PC=xxxx PS=xxxx T0 N0 Z0 V0 C0
|
||||
* MMR0=xxxxxx MMR1=xxxxxx MMR2=xxxxxx MMR3=xxxxxx ER=xxxxxx
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
* @return {string}
|
||||
*/
|
||||
DebuggerPDP11.prototype.getRegDump = function()
|
||||
DebuggerPDP11.prototype.getMiscDump = function()
|
||||
{
|
||||
var sDump = "";
|
||||
sDump += this.getRegOutput(DebuggerPDP11.REG_MMR0) + this.getRegOutput(DebuggerPDP11.REG_MMR1);
|
||||
sDump += this.getRegOutput(DebuggerPDP11.REG_MMR2) + this.getRegOutput(DebuggerPDP11.REG_MMR3) + this.getRegOutput(DebuggerPDP11.REG_ERR);
|
||||
sDump += '\n';
|
||||
sDump += this.getRegOutput(DebuggerPDP11.REG_SR) + this.getRegOutput(DebuggerPDP11.REG_AR) + this.getRegOutput(DebuggerPDP11.REG_DR);
|
||||
return sDump;
|
||||
};
|
||||
|
||||
/**
|
||||
* getRegDump(fMisc)
|
||||
*
|
||||
* Sample register dump:
|
||||
*
|
||||
* R0=xxxxxx R1=xxxxxx R2=xxxxxx R3=xxxxxx R4=xxxxxx R5=xxxxxx
|
||||
* SP=xxxxxx PC=xxxxxx PS=xxxxxx IR=xxxxxx SL=xxxxxx T0 N0 Z0 V0 C0
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
* @param {boolean} [fMisc] (true to include misc registers)
|
||||
* @return {string}
|
||||
*/
|
||||
DebuggerPDP11.prototype.getRegDump = function(fMisc)
|
||||
{
|
||||
var i;
|
||||
var sDump = "";
|
||||
|
|
@ -2423,8 +2536,9 @@ if (DEBUGGER) {
|
|||
}
|
||||
sDump += '\n';
|
||||
sDump += this.getRegOutput(PDP11.REG.SP) + this.getRegOutput(PDP11.REG.PC);
|
||||
sDump += this.getRegOutput(DebuggerPDP11.REG_PSW) + this.getRegOutput(DebuggerPDP11.REG_SR);
|
||||
sDump += this.getRegOutput(DebuggerPDP11.REG_PSW) + this.getRegOutput(DebuggerPDP11.REG_PIR) + this.getRegOutput(DebuggerPDP11.REG_SL);
|
||||
sDump += this.getFlagOutput('T') + this.getFlagOutput('N') + this.getFlagOutput('Z') + this.getFlagOutput('V') + this.getFlagOutput('C');
|
||||
if (fMisc) sDump += '\n' + this.getMiscDump();
|
||||
return sDump;
|
||||
};
|
||||
|
||||
|
|
@ -3390,77 +3504,115 @@ if (DEBUGGER) {
|
|||
if (asArgs && asArgs[1] == '?') {
|
||||
this.println("register commands:");
|
||||
this.println("\tr\tdump registers");
|
||||
this.println("\trm\tdump misc registers");
|
||||
this.println("\trx [#]\tset flag or register x to [#]");
|
||||
return;
|
||||
}
|
||||
|
||||
var fMisc = false;
|
||||
var cpu = this.cpu;
|
||||
if (fInstruction == null) fInstruction = true;
|
||||
|
||||
if (asArgs != null && asArgs.length > 1) {
|
||||
var sReg = asArgs[1];
|
||||
var sValue = null;
|
||||
var i = sReg.indexOf('=');
|
||||
if (i > 0) {
|
||||
sValue = sReg.substr(i + 1);
|
||||
sReg = sReg.substr(0, i);
|
||||
}
|
||||
else if (asArgs.length > 2) {
|
||||
sValue = asArgs[2];
|
||||
|
||||
if (sReg == 'm') {
|
||||
fMisc = true;
|
||||
}
|
||||
else {
|
||||
this.println("missing value for " + asArgs[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
var w = this.parseExpression(sValue);
|
||||
if (w === undefined) return;
|
||||
|
||||
var sRegMatch = sReg.toUpperCase();
|
||||
switch (sRegMatch) {
|
||||
case "SP":
|
||||
case "R6":
|
||||
cpu.setSP(w);
|
||||
break;
|
||||
case "PC":
|
||||
case "R7":
|
||||
cpu.setPC(w);
|
||||
this.dbgAddrNextCode = this.newAddr(cpu.getPC());
|
||||
break;
|
||||
case "N":
|
||||
if (w) cpu.setNF(); else cpu.clearNF();
|
||||
break;
|
||||
case "Z":
|
||||
if (w) cpu.setZF(); else cpu.clearZF();
|
||||
break;
|
||||
case "V":
|
||||
if (w) cpu.setVF(); else cpu.clearVF();
|
||||
break;
|
||||
case "C":
|
||||
if (w) cpu.setCF(); else cpu.clearCF();
|
||||
break;
|
||||
case "SR":
|
||||
if (this.panel && this.panel.hasSwitches()) {
|
||||
this.panel.setSR(w);
|
||||
break;
|
||||
var sValue = null;
|
||||
var i = sReg.indexOf('=');
|
||||
if (i > 0) {
|
||||
sValue = sReg.substr(i + 1);
|
||||
sReg = sReg.substr(0, i);
|
||||
}
|
||||
/* falls through */
|
||||
default:
|
||||
if (sRegMatch.charAt(0) == 'R') {
|
||||
var iReg = +sRegMatch.charAt(1);
|
||||
if (iReg >= 0 && iReg < 6) {
|
||||
cpu.regsGen[iReg] = w & 0xffff;
|
||||
else if (asArgs.length > 2) {
|
||||
sValue = asArgs[2];
|
||||
}
|
||||
else {
|
||||
this.println("missing value for " + asArgs[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
var w = this.parseExpression(sValue);
|
||||
if (w === undefined) return;
|
||||
|
||||
var sRegMatch = sReg.toUpperCase();
|
||||
switch (sRegMatch) {
|
||||
case "SP":
|
||||
case "R6":
|
||||
cpu.setSP(w);
|
||||
break;
|
||||
case "PC":
|
||||
case "R7":
|
||||
cpu.setPC(w);
|
||||
this.dbgAddrNextCode = this.newAddr(cpu.getPC());
|
||||
break;
|
||||
case "N":
|
||||
if (w) cpu.setNF(); else cpu.clearNF();
|
||||
break;
|
||||
case "Z":
|
||||
if (w) cpu.setZF(); else cpu.clearZF();
|
||||
break;
|
||||
case "V":
|
||||
if (w) cpu.setVF(); else cpu.clearVF();
|
||||
break;
|
||||
case "C":
|
||||
if (w) cpu.setCF(); else cpu.clearCF();
|
||||
break;
|
||||
case "PS":
|
||||
cpu.setPSW(w);
|
||||
break;
|
||||
case "IR":
|
||||
cpu.setPIR(w);
|
||||
break;
|
||||
case "ER":
|
||||
cpu.regErr = w;
|
||||
fMisc = true;
|
||||
break;
|
||||
case "SL":
|
||||
cpu.setSL(w);
|
||||
break;
|
||||
case "MMR0":
|
||||
cpu.setMMR0(w);
|
||||
fMisc = true;
|
||||
break;
|
||||
case "MMR3":
|
||||
cpu.setMMR3(w);
|
||||
fMisc = true;
|
||||
break;
|
||||
case "AR":
|
||||
if (this.panel) this.panel.setAR(w);
|
||||
fMisc = true;
|
||||
break;
|
||||
case "DR":
|
||||
if (this.panel) this.panel.setDR(w);
|
||||
fMisc = true;
|
||||
break;
|
||||
case "SR":
|
||||
if (this.panel && this.panel.hasSwitches()) {
|
||||
this.panel.setSR(w);
|
||||
fMisc = true;
|
||||
break;
|
||||
}
|
||||
/* falls through */
|
||||
default:
|
||||
if (sRegMatch.charAt(0) == 'R') {
|
||||
var iReg = +sRegMatch.charAt(1);
|
||||
if (iReg >= 0 && iReg < 6) {
|
||||
cpu.regsGen[iReg] = w & 0xffff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.println("unknown register: " + sReg);
|
||||
return;
|
||||
}
|
||||
this.println("unknown register: " + sReg);
|
||||
return;
|
||||
this.cmp.updateDisplays();
|
||||
this.println("updated registers:");
|
||||
}
|
||||
this.cmp.updateDisplays();
|
||||
this.println("updated registers:");
|
||||
}
|
||||
|
||||
this.println(this.getRegDump());
|
||||
this.println(this.getRegDump(fMisc));
|
||||
|
||||
if (fInstruction) {
|
||||
this.dbgAddrNextCode = this.newAddr(cpu.getPC());
|
||||
|
|
@ -3716,7 +3868,7 @@ if (DEBUGGER) {
|
|||
* a final updateDisplays().
|
||||
*/
|
||||
if (dbg.panel && dbg.panel.stop) dbg.panel.stop();
|
||||
dbg.cmp.updateDisplays();
|
||||
dbg.cmp.updateDisplays(-1);
|
||||
dbg.setBusy(false);
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ var PDP11 = {
|
|||
ENABLED: 0x0001, // 000001 address relocation enabled
|
||||
PAGE_NUM: 0x000E, // 000016 page number of last fault
|
||||
PAGE_D: 0x0010, // 000020 last fault occurred in D space
|
||||
PAGE: 0x001E, // 000176 all of the PAGE bits
|
||||
PAGE: 0x001E, // 000176 (all of the PAGE bits)
|
||||
MODE: 0x0060, // 000140 processor mode as of last fault
|
||||
COMPLETED: 0x0080, // 000200 last instruction completed (R/O)
|
||||
DSTMODE: 0x0100, // 000400 only destination mode references will be relocated (aka MAINT bit)
|
||||
|
|
@ -333,7 +333,7 @@ var PDP11 = {
|
|||
ABORT_RO: 0x2000, // 020000 abort: read-only
|
||||
ABORT_PL: 0x4000, // 040000 abort: page length
|
||||
ABORT_NR: 0x8000, // 100000 abort: non-resident
|
||||
ABORT: 0xE000, // 160000
|
||||
ABORT: 0xE000, // 160000 (all of the ABORT bits)
|
||||
UPDATE: 0xF0FE // Includes all of: ABORT, TRAP, COMPLETED, MODE, and PAGE bits
|
||||
},
|
||||
MMR1: { // 177574: general purpose auto-inc/auto-dec register
|
||||
|
|
|
|||
|
|
@ -176,6 +176,50 @@ PanelPDP11.LED = {
|
|||
B22: 'B22'
|
||||
};
|
||||
|
||||
/**
|
||||
* getAR()
|
||||
*
|
||||
* @this {PanelPDP11}
|
||||
* @return {number} (current ADDRESS register)
|
||||
*/
|
||||
PanelPDP11.prototype.getAR = function()
|
||||
{
|
||||
return this.regAddr;
|
||||
};
|
||||
|
||||
/**
|
||||
* setAR(value)
|
||||
*
|
||||
* @this {PanelPDP11}
|
||||
* @param {number} value (new ADDRESS register)
|
||||
*/
|
||||
PanelPDP11.prototype.setAR = function(value)
|
||||
{
|
||||
this.updateAddr(this.regAddr = value);
|
||||
};
|
||||
|
||||
/**
|
||||
* getDR()
|
||||
*
|
||||
* @this {PanelPDP11}
|
||||
* @return {number} (current DISPLAY register)
|
||||
*/
|
||||
PanelPDP11.prototype.getDR = function()
|
||||
{
|
||||
return this.regDisplay;
|
||||
};
|
||||
|
||||
/**
|
||||
* setDR(value)
|
||||
*
|
||||
* @this {PanelPDP11}
|
||||
* @param {number} value (new DISPLAY register)
|
||||
*/
|
||||
PanelPDP11.prototype.setDR = function(value)
|
||||
{
|
||||
this.updateData(this.regDisplay = value);
|
||||
};
|
||||
|
||||
/**
|
||||
* getSR()
|
||||
*
|
||||
|
|
@ -1004,7 +1048,7 @@ PanelPDP11.prototype.updateDisplay = function(nUpdate)
|
|||
* TODO: There is currently no mechanism for selecting regData over regDisplay;
|
||||
* we are acting as if the DATASEL switch setting is locked to "DISPLAY REGISTER".
|
||||
*/
|
||||
this.updateAddr(nUpdate > 0 && fRunning && !fWaiting? this.cpu.getPC() : this.regAddr);
|
||||
this.updateAddr(nUpdate > 0 && fRunning && !fWaiting? this.cpu.getLastAddr() : this.regAddr);
|
||||
this.updateData(this.regDisplay);
|
||||
|
||||
var bits = this.cpu.getMMUState();
|
||||
|
|
|
|||
|
|
@ -244,6 +244,10 @@ SerialPortPDP11.prototype.setBinding = function(sType, sBinding, control, sValue
|
|||
if (event.preventDefault) event.preventDefault();
|
||||
var clipboardData = event.clipboardData || window.clipboardData;
|
||||
if (clipboardData) {
|
||||
/*
|
||||
* NOTE: Multiple lines of pasted text will (at least on macOS) contain LFs instead of CRs;
|
||||
* this is dealt with in receiveData() whenever it receives a string of characters.
|
||||
*/
|
||||
serial.receiveData(clipboardData.getData('Text'));
|
||||
}
|
||||
};
|
||||
|
|
@ -522,8 +526,20 @@ SerialPortPDP11.prototype.receiveData = function(data)
|
|||
this.abReceive.push(data);
|
||||
}
|
||||
else if (typeof data == "string") {
|
||||
var b = 0, bPrev;
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
this.abReceive.push(data.charCodeAt(i));
|
||||
bPrev = b;
|
||||
b = data.charCodeAt(i);
|
||||
/*
|
||||
* NOTE: Multiple lines of pasted text will (at least on macOS) contain LFs instead of CRs;
|
||||
* we convert them to CRs below. Windows may do something different, but in the worst case,
|
||||
* even if we receive CR/LF pairs, this code should keep the CRs and lose the LFs.
|
||||
*/
|
||||
if (b == str.ASCII.LF) {
|
||||
if (bPrev == str.ASCII.CR) continue;
|
||||
b = str.ASCII.CR;
|
||||
}
|
||||
this.abReceive.push(b);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -551,6 +551,10 @@ str.trim = function(s)
|
|||
/*
|
||||
* Any codes commented out in the following table are deemed "printable"
|
||||
*/
|
||||
str.ASCII = {
|
||||
LF: 0x0A,
|
||||
CR: 0x0D
|
||||
};
|
||||
str.aASCIICodes = {
|
||||
0x00: "NUL",
|
||||
0x01: "SOH", // (CTRL_A) Start of Heading
|
||||
|
|
|
|||
Loading…
Reference in a new issue