diff --git a/SYMBOL/DCMCP.esp_m b/SYMBOL/DCMCP.esp_m index 17dcf35..94307ad 100644 --- a/SYMBOL/DCMCP.esp_m +++ b/SYMBOL/DCMCP.esp_m @@ -6571,3 +6571,103 @@ PROCEDURE TABLEOFCONTENTS(B,COUNT);% 07268000 DS~6 LIT " THRU ";% 07295190 SI~SI+4; DS~4 CHR;% 07295200 END;% 07295210 + DS~LIT "~"; 07295220 + END;% 07295230 + SPOUT(I);% 07295235 + END ELSE FORGETSPACE(I);% 07295240 + $ POP OMIT 07295241 + UNLOCKCONTROLKECKS; 07296000 + END;% 07297000 + PROCEDURE REMOVEDECK(N,TUSTA);VALUE N,TUSTA;REAL N,TUSTA; 07298000 + BEGIN REAL I,T,A,L1,J=I,L2,V;% 07299000 + $ SET OMIT = NOT(PACKETS) 07299499 + REAL L3; 07299500 + LABEL FAIL,CONTINUE; 07299600 + $ POP OMIT 07299601 + LABEL L,EXIT,REMOVE;% 07300000 + LOCKCONTROLDECKS; 07301000 + IF (I ~ DIRECTORYSEARCH("DECK ",N,5)) = 0 THEN% 07303000 + $ SET OMIT = NOT(PACKETS) 07303499 + FAIL: 07303500 + $ POP OMIT 07303501 + BEGIN I ~ SPACE(5);% 07304000 + STREAM(N,I);% 07305000 + $ SET OMIT = NOT(PACKETS) 07305099 + BEGIN DS:=5 LIT " PKT "; 07305100 + $ POP OMIT 07305101 + $ SET OMIT = PACKETS 07305999 + SI ~ LOC N; SI ~ SI+1; DS ~ 5 CHR;% 07307000 + DS ~ 13 LIT " NOT ON DISK~";% 07308000 + END;% 07309000 + GO TO EXIT;% 07310000 + END;% 07311000 + $ SET OMIT = NOT(SHAREDISK) 07311199 + $ SET OMIT = NOT(PACKETS) 07311499 + L3:=M[I+6].[FF]; 07311500 + $ POP OMIT 07311501 + L2:=M[I+6].[CF]; 07312000 + IF (A:=FIRSTDECK)=(L1:=I.[FF]) THEN 07313000 + BEGIN 07314000 + $ SET OMIT = PACKETS 07314099 + $ SET OMIT = NOT(PACKETS) 07314109 + FIRSTDECK:=IF L3 NEQ 0 THEN L3 ELSE L2; 07314110 + IF L2=0 THEN LASTDECK~IF L3 NEQ 0 THEN L3 ELSE 0; 07314120 + $ POP OMIT 07314121 + DISKWAIT(KLUMP,3,DIRECTORYTOP+3); 07314200 + $ SET OMIT = NOT(PACKETS) 07314289 + IF L3 NEQ 0 THEN GO TO CONTINUE ELSE 07314290 + $ POP OMIT 07314291 + GO TO REMOVE; 07314300 + END; 07314400 + J ~ I.[33:15];% 07315000 + L: 07316000 + DISKWAIT(-J,30,A); 07317000 + IF (V:=M[J+6].[CF])=0 THEN 07318000 + $ SET OMIT = NOT(PACKETS) 07318009 + IF A=L1 THEN GO REMOVE ELSE BEGIN FORGETSPACE(I); GO FAIL 07318010 + END; 07318012 + $ POP OMIT 07318013 + $ SET OMIT = PACKETS 07318019 + IF V ! L1 THEN% 07319000 + BEGIN A ~ V; GO TO L END;% 07320000 + $ SET OMIT = PACKETS 07320999 + $ SET OMIT = NOT(PACKETS) 07321099 + M[J+6].[CF]~IF L3!0 THEN L3 ELSE L2; 07321100 + $ POP OMIT 07321101 + DISKWAIT(J,30,A); 07322000 + IF L2 = 0 THEN% 07324000 + BEGIN 07325000 + $ SET OMIT = PACKETS 07325999 + $ SET OMIT = NOT(PACKETS) 07326099 + LASTDECK:=IF L3 NEQ 0 THEN L3 ELSE A; 07326100 + $ POP OMIT 07326101 + DISKWAIT(KLUMP,3,DIRECTORYTOP+3); 07327000 + $ SET OMIT = PACKETS 07327999 + $ SET OMIT = NOT(PACKETS) 07329999 + END ELSE IF L3=0 THEN ELSE 07330000 + CONTINUE: 07330050 + BEGIN J~I INX 0; 07330100 + DISKWAIT(-J,30,L3); 07330200 + M[J+6].[CF]~L2; 07330300 + DISKWAIT(J,30,L3); 07330400 + END; 07330500 + $ POP OMIT 07330501 + REMOVE: 07331000 + FORGETSPACE(I); 07332000 + I:=DIRECTORYSEARCH("DECK ",N,8).[CF]; 07333000 + T ~ M[I+9];% 07343000 + FOR V ~ 1 STEP 1 UNTIL T DO% 07344000 + IF M[I+V+9]!0 THEN FORGETUSREDISK(M[I+V+9],M[I+8]); 07345000 + STREAM(N,I);% 07346000 + $ SET OMIT = NOT(PACKETS) 07346099 + BEGIN DS:=5 LIT " PKT "; 07346100 + $ POP OMIT 07346101 + $ SET OMIT = PACKETS 07346999 + SI ~ LOC N; SI ~ SI+1; DS ~ 5 CHR;% 07348000 + DS ~ 9 LIT " REMOVED~";% 07349000 + END;% 07350000 + $ SET OMIT = PACKETS 07350099 +EXIT: SPOUTER(I&TUSTA[9:9:9],TUSTA,LIBMSG) 07351000 + $ SET OMIT = PACKETS 07351099 + ;UNLOCKCONTROLDECKS; 07352000 + END;% 07353000 diff --git a/emulator/B5500CentralControl.js b/emulator/B5500CentralControl.js index 8c99b89..3c9bdc5 100644 --- a/emulator/B5500CentralControl.js +++ b/emulator/B5500CentralControl.js @@ -32,7 +32,7 @@ function B5500CentralControl() { this.MemMod = new Array(8); // Array of memory module words as Float64s (8 x 4KW each) // Instance variables and flags - this.poweredUp = false; // System power indicator + this.poweredUp = 0; // System power indicator this.PB1L = 0; // 0=> PA is P1, 1=> PB is P1 this.cardLoadSelect = 0; // 0=> load from disk/drum; 1=> load from cards @@ -504,7 +504,7 @@ B5500CentralControl.prototype.halt = function() { /* Halts the processors. Any in-process I/Os are allowed to complete */ if (this.PA && this.PA.busy) { - this.PA.busy = false; + this.PA.busy = 0; this.PA.cycleLimit = 0; if (this.PA.scheduler) { clearTimeout(this.PA.scheduler); @@ -513,7 +513,7 @@ B5500CentralControl.prototype.halt = function() { } if (this.PB && this.PB.busy) { - this.PB.busy = false; + this.PB.busy = 0; this.PB.cycleLimit = 0; if (this.PB.scheduler) { clearTimeout(this.PB.scheduler); @@ -604,7 +604,7 @@ B5500CentralControl.prototype.powerOn = function() { if (!this.poweredUp) { this.configureSystem(); - this.poweredUp = true; + this.poweredUp = 1; } }; @@ -634,6 +634,6 @@ B5500CentralControl.prototype.powerOff = function() { this.AddressSpace[x] = null; } - this.poweredUp = false; + this.poweredUp = 0; } }; diff --git a/emulator/B5500Processor.js b/emulator/B5500Processor.js index 0d7b287..6e06c7b 100644 --- a/emulator/B5500Processor.js +++ b/emulator/B5500Processor.js @@ -98,7 +98,7 @@ B5500Processor.prototype.clear = function() { this.totalCycles = 0; // Total cycles executed on this processor this.procTime = 0; // Current processor running time, based on cycles executed this.scheduleSlack = 0; // Total processor throttling delay, milliseconds - this.busy = false; // Proessor is running, not idle or halted + this.busy = 0; // Proessor is running, not idle or halted }; /**************************************/ @@ -185,14 +185,14 @@ B5500Processor.prototype.access = function(eValue) { if (this.NCSF || this !== cc.P1) { cc.signalInterrupt(); } else { - this.busy = false; // P1 invalid address in control state stops the proc + this.busy = 0; // P1 invalid address in control state stops the proc } } else if (acc.MPED) { this.I |= 0x01; // set I01F - memory parity error if (this.NCSF || this !== cc.P1) { cc.signalInterrupt(); } else { - this.busy = false; // P1 memory parity in control state stops the proc + this.busy = 0; // P1 memory parity in control state stops the proc } } }; @@ -430,7 +430,7 @@ B5500Processor.storeForInterrupt = function(forTest) { this.T = 0; // idle the processor this.TROF = 0; this.PROF = 0; - this.busy = false; + this.busy = 0; cc.HP2F = 1; cc.P2BF = 0; if (cc.P2.scheduler) { @@ -454,7 +454,7 @@ B5500Processor.storeForInterrupt = function(forTest) { this.T = 0; // idle the processor this.TROF = 0; this.PROF = 0; - this.busy = false; + this.busy = 0; cc.HP2F = 1; cc.P2BF = 0; if (cc.P2.scheduler) { @@ -558,7 +558,7 @@ B5500Processor.initiate = function(forTest) { } } else { this.NCSF = 1; - this.busy = true; + this.busy = 1; } }; @@ -612,11 +612,11 @@ B5500Processor.prototype.computeRelativeAddr = function(offset, cEnabled) { /**************************************/ B5500Processor.prototype.indexDescriptor = function() { /* Indexes a descriptor and, if successful leaves the indexed value in - the A register. Returns true if an interrupt is set and the syllable is + the A register. Returns 1 if an interrupt is set and the syllable is to be exited */ var aw = this.A; // local copy of A reg var bw; // local copy of B reg - var interrupted = false; // fatal error, interrupt set + var interrupted = 0; // fatal error, interrupt set var xe; // index exponent var xm; // index mantissa var xo; // last index octade shifted off @@ -643,7 +643,7 @@ B5500Processor.prototype.indexDescriptor = function() { xm *= 8; } else { // oops... integer overflow normalizing the index xe = 0; // kill the loop - interrupted = true; + interrupted = 1; if (this.NCSF) { this.I = (this.I & 0x0F) | 0xC0; // set I07/8: int-overflow cc.signalInterrupt(); @@ -657,13 +657,13 @@ B5500Processor.prototype.indexDescriptor = function() { // Now we have an integerized index value in xm if (!interrupted) { if (xm && cc.bit(bw, 1)) { // oops... negative index - interrupted = true; + interrupted = 1; if (this.NCSF) { this.I = (this.I & 0x0F) | 0x90; // set I05/8: invalid-index cc.signalInterrupt(); } } else if (xm >= cc.fieldIsolate(bw, 8, 10)) { - interrupted = true; // oops... index out of bounds + interrupted = 1; // oops... index out of bounds if (this.NCSF) { this.I = (this.I & 0x0F) | 0x90; // set I05/8: invalid-index cc.signalInterrupt(); @@ -736,12 +736,17 @@ B5500Processor.prototype.buildRCW = function(descriptorCall) { }; /**************************************/ -B5500Processor.prototype.applyRCW = function(word) { +B5500Processor.prototype.applyRCW = function(word, inline) { /* Set processor state from fields of the Return Control Word in - the "word" parameter. Returns the state of the OPDC/DESC bit [2:1] */ + the "word" parameter. If "inline" is truthy, C & L are NOT restored from + the RCW. Returns the state of the OPDC/DESC bit [2:1] */ var f; - this.C = f = word % 0x8000; // [33:15] + f = word % 0x8000; // [33:15] + if (!inline) { + this.C = f; + this.access(0x30); // P = [C], fetch new program word + } word = (word-f)/0x8000; this.F = f = word % 0x8000; // [18:15] word = (word-f)/0x8000; @@ -749,7 +754,10 @@ B5500Processor.prototype.applyRCW = function(word) { word = (word-f)/0x08; this.G = f = word % 0x08; // [12:3] word = (word-f)/0x08; - this.L = f = word % 0x04; // [10:2] + f = word % 0x04; // [10:2] + if (!inline) { + this.L = f; + } word = (word-f)/0x04; this.V = f = word % 0x08; // [7:3] word = (word-f)/0x08; @@ -770,7 +778,7 @@ B5500Processor.prototype.enterCharModeInline() { } else { this.access(0x02) // A = [S]: tank the DI address } - this.B = this.buildRCW(false); + this.B = this.buildRCW(0); this.adjustBEmpty(); this.MSFF = 0; this.SALF = 1; @@ -852,9 +860,10 @@ B5500Processor.prototype.enterSubroutine = function(descriptorCall) { }; /**************************************/ -B5500Processor.prototype.exitSubroutine = function() { +B5500Processor.prototype.exitSubroutine = function(inline) { /* Exits a subroutine by restoring the processor state from RCW and MSCW words - in the stack. The RCW is assumed to be in the B register, pointing to the MSCW. + in the stack. "inline" indicates the C & L registers are NOT restored from the + RCW. The RCW is assumed to be in the B register, pointing to the MSCW. The A register is not affected by this routine. If SALF & MSFF bits in the MSCW are set, link back through the MSCWs until one is found that has either bit not set, and store that MSCW at [R]+7. This is the last prior MSCW that actually @@ -873,9 +882,8 @@ B5500Processor.prototype.exitSubroutine = function() { cc.signalInterrupt(); } } else { // flag bit is set - result = this.applyRCW(this.B); + result = this.applyRCW(this.B, inline); this.X = this.B % 0x8000000000; // save F setting from MSCW to restore S at end - this.access(0x30); // P = [C], C set from RCW this.S = this.F; this.access(0x03); // B = [S], fetch the MSCW @@ -902,7 +910,7 @@ B5500Processor.prototype.operandCall = function() { machines. Assumes the syllable has already loaded a word into A. See Figures 6-1, 6-3, and 6-4 in the B5500 Reference Manual */ var aw; // local copy of A reg value - var interrupted = false; // interrupt occurred + var interrupted = 0; // interrupt occurred aw = this.A; if (aw >= 0x800000000000) { @@ -928,7 +936,7 @@ B5500Processor.prototype.operandCall = function() { case 7: // Present program descriptor - this.enterSubroutine(false); + this.enterSubroutine(0); break; case 0: @@ -962,7 +970,7 @@ B5500Processor.prototype.descriptorCall = function() { that the address of that word is in M. See Figures 6-2, 6-3, and 6-4 in the B5500 Reference Manual */ var aw = this.A; // local copy of A reg value - var interrupted = false; // interrupt occurred + var interrupted = 0; // interrupt occurred if (aw < 0x800000000000) { // It's a simple operand @@ -982,7 +990,7 @@ B5500Processor.prototype.descriptorCall = function() { case 7: // Present program descriptor - this.enterSubroutine(true); + this.enterSubroutine(1); break; case 0: @@ -1039,6 +1047,13 @@ B5500Processor.prototype.run = function() { variant = opcode >>> 6; switch (opcode & 0x3F) { case 0x00: // XX00: CMX, EXC: Exit character mode + this.adjustBEmpty(); // store destination string + this.S = this.F; + this.access(0x03); // B = [S], fetch the RCW + this.exitSubroutine(variant & 0x01); // exit vs. exit inline + this.AROF = this.BROF = 0; + this.X = this.M = this.N = 0; + this.CWMF = 0; break; case 0x02: // XX02: BSD=Skip bit destination @@ -1082,11 +1097,11 @@ B5500Processor.prototype.run = function() { break; case 0x18: // 3011: SFI=Store for Interrupt - this.storeForInterrupt(false); + this.storeForInterrupt(0); break; case 0x1C: // 3411: SFT=Store for Test - this.storeForInterrupt(true); + this.storeForInterrupt(1); break; default: // Anything else is a no-op @@ -1253,14 +1268,14 @@ B5500Processor.prototype.run = function() { case 2: // OPDC: Operand Call this.adjustAEmpty(); - computeRelativeAddr(opcode >>> 2, true); + computeRelativeAddr(opcode >>> 2, 1); this.access(0x04); // A = [M] this.operandCall(); break; case 3: // DESC: Descriptor (name) Call this.adjustAEmpty(); - computeRelativeAddr(opcode >>> 2, true); + computeRelativeAddr(opcode >>> 2, 1); this.access(0x04); // A = [M] this.descriptorCall(); break; @@ -1346,7 +1361,7 @@ B5500Processor.prototype.run = function() { if (!this.NCSF && cc.P2 && cc.P2BF) { cc.HP2F = 1; // We know P2 is not currently running on this thread, so save its registers - cc.P2.storeForInterrupt(false); + cc.P2.storeForInterrupt(0); } break; @@ -1354,16 +1369,16 @@ B5500Processor.prototype.run = function() { break; case 0x18: // 3011: SFI=Store for Interrupt - this.storeForInterrupt(false); + this.storeForInterrupt(0); break; case 0x1C: // 3411: SFT=Store for Test - this.storeForInterrupt(true); + this.storeForInterrupt(1); break; case 0x21: // 4111: IP1=Initiate Processor 1 if (!this.NCSF) { - this.initiate(false); + this.initiate(0); } break; @@ -1652,7 +1667,7 @@ B5500Processor.prototype.run = function() { this.adjustAFull(); this.S = this.F; this.access(0x03); // B = [S], fetch the RCW - switch (this.exitSubroutine()) { + switch (this.exitSubroutine(0)) { case 0: this.X = 0; operandCall(); @@ -1667,13 +1682,13 @@ B5500Processor.prototype.run = function() { this.AROF = 0; this.S = this.F; this.access(0x03); // B = [S], fetch the RCW - this.exitSubroutine(); + this.exitSubroutine(0); break; case 0x0A: // 1235: RTS=return special this.adjustAFull(); this.access(0x03); // B = [S], fetch the RCW - switch (this.exitSubroutine()) { + switch (this.exitSubroutine(0)) { case 0: this.X = 0; operandCall(); @@ -1681,6 +1696,8 @@ B5500Processor.prototype.run = function() { this.Q |= 0x10; // set Q05F, for display only this.X = 0; descriptorCall(); + case 2: // flag-bit interrupt occurred, do nothing + break; } break; } @@ -1709,7 +1726,7 @@ B5500Processor.prototype.run = function() { this.adjustBEmpty(); this.F = this.S; if (!this.MSFF) { - if (this.SALF) { + if (this.SALF) { // store the MSCW at R+7 this.M = (this.R*64) + 7; this.access(0x0D); // [M] = B }