mirror of
https://github.com/pkimpel/retro-b5500.git
synced 2026-02-12 11:17:29 +00:00
Commit DCMCP transcription as of 2012-06-30; commit minor tweaks to
processor panel prototype; commit Nigel's preliminary changes to Processor module
This commit is contained in:
@@ -5157,3 +5157,148 @@ BEGIN 06096600
|
||||
TEMPDISK:=1; 06100200
|
||||
GO TO MVE; 06100300
|
||||
END; 06100400
|
||||
I:=MV[I+2].LINK; 06100500
|
||||
END; 06100600
|
||||
% WILL NOW RECONFIGURE THE AVAILABLE TABLE 06100700
|
||||
UT[AV]:=HI&(UT[AV].ASIZE+UT[AV+I].ASIZE)[2:28:20]; 06100800
|
||||
MOVE(S-AV,P([UT[AV+2]],DUP),NOT 0 INX P(XCH)); 06100900
|
||||
C:=(S:=S-1)-1; FOR I:=C STEP -1 UNTIL D DO 06101000
|
||||
IF P(UT[I].ASIZE,DUP)>USE THEN USE:=P ELSE P(DEL); 06101100
|
||||
U[EU]:=P(DUP,LOD,DUP)&USE[1:28:20]&(P(XCH).NUMENT-1)[TONUMENT]; 06101200
|
||||
EUNOTSQUASHED:=FALSE; 06101300
|
||||
IF NOT SQALL THEN 06101400
|
||||
BEGIN 06101500
|
||||
IF P(SQSIZE,DUP)!0 AND P(XCH) LEQ USE THEN CELL:=1 06101600
|
||||
ELSE IF P(EUS[EU-1],DSIZE,DUP)!0 AND P(XCH) LEQ USE 06101700
|
||||
THEN ELSE GO TO ENDMVE; 06101800
|
||||
P(DEL); GO STOPSQ; 06101900
|
||||
END; 06102000
|
||||
ENDMVE: 06102100
|
||||
END FIXING AND MOVING; 06102200
|
||||
$ SET OMIT = NOT SHAREDISK 06102220
|
||||
P(0,0,0,0,0,0,0,0,0,0); 06102500
|
||||
P(0,0,0,0,0,0,0,0,0,0); 06102600
|
||||
P(0,0,0,0,0,0,0,0,0,0); 06102700
|
||||
P(0,0,0,0,0,0,0,0,0); 06102800
|
||||
P(.DISKSQUASH,DUP,M[(P)]); % PRTADDR,PRTVALUE 06102900
|
||||
$ SET OMIT = NOT SHAREDISK 06103000
|
||||
SCANMESSAGE; 06103300
|
||||
$ SET OMIT = SHAREDISK 06103400
|
||||
LOCKDIRECTORY; 06103500
|
||||
$ POP OMIT 06103600
|
||||
SLEEP([TOGLE],USERDISKMASK); LOCKTOG(USERDISKMASK); 06103700
|
||||
HALT; % STOP NORMAL STATE PROCESSING WHILE SQUASHING 06103800
|
||||
A4:=SPACE(30); 06103900
|
||||
$ SET OMIT = NOT SHAREDISK 06104000
|
||||
FIXARRAY(DIR,A1,480); FIXARRAY(MV,A2,150); 06107200
|
||||
A3:=SPACE(900); 06107300
|
||||
IOD:=@140000100000000&(A3-1)[CTC]; 06107400
|
||||
IF NOT SQALL THEN FOR EU:=1 STEP 1 UNTIL NEUP.[FF] DO 06107900
|
||||
IF (CELL:=(P(SQSIZE,DUP)!0 AND P(XCH) LEQ U[EU].[1:20])) 06108000
|
||||
THEN BEGIN P(2); SQUASHMESS; GO STOPIT END; 06108100
|
||||
FOR EU:=1 STEP 1 UNTIL NEUP.[FF] DO % 06108200
|
||||
IF NOT (E:=U[EU]).EUNP THEN % NOT A DUMMY EU 06108300
|
||||
IF EUS[EU-1] OR SQALL OR SQSIZE!0 THEN % SQUASH THIS EU 06108400
|
||||
BEGIN 06108500
|
||||
EUNOTSQUASHED:=TRUE; 06108600
|
||||
IF NOT SQALL THEN % CHECK IF SQUASH IS NECESSARY 06108700
|
||||
IF (P(EUS[EU-1].DSIZE,DUP) LEQ E.[1:20] AND P(XCH)!0) 06108800
|
||||
THEN BEGIN P(3); SQUASHMESS; GO STOPIT END; 06108900
|
||||
CELL:=0&1[CTF]; 06109000
|
||||
P(0); SQUASHMESS; 06109100
|
||||
D:=(I:=E.STARTWRD) MOD 30; 06109200
|
||||
AVSIZE:=30-(S:=(E AND NUMENTM)+D) MOD 30+S; 06109300
|
||||
FIXARRAY(UT,R,AVSIZE); 06109400
|
||||
DISKAV:=I DIV 30+USERDISKBOTTOM; 06109500
|
||||
$ SET OMIT = NOT SHAREDISK 06109600
|
||||
DISKWAIT(-R,AVSIZE,DISKAV); 06110300
|
||||
AGAIN: SUM:=USE:=0; 06110400
|
||||
FOR I:=S-3 STEP -1 UNTIL D DO 06110500
|
||||
BEGIN STOPCK; 06110600
|
||||
IF (UT[I+1]<0)=PASSTWO THEN % NOT CHECKED THIS PASS 06110700
|
||||
IF ((X1:=UT[I].ASIZE)+(X2:=UT[I+1].ASIZE)) GEQ SUM 06110800
|
||||
THEN IF (X3:=(((X4:=UT[I+1].DEND)-1)-UT[I+1].ASIZE)- 06110900
|
||||
X5:=(UT[I].DEND-1)) LEQ FACTOR THEN IF MINSIZE LEQ X2 06111000
|
||||
THEN IF MINSIZE LEQ X1 THEN 06111100
|
||||
BEGIN 06111200
|
||||
SQIT: USE:=X3; AV:=I; 06111300
|
||||
SUM:=X1-X2; % SUM OF CURRENT AVAILABLE AREAS 06111400
|
||||
HI:=X4; LO:=X5; 06111500
|
||||
END ELSE IF I!0 THEN % LOOK AHEAD TO NEXT AREA 06111600
|
||||
IF ((MINSIZE LEQ UT[I-1].ASIZE) AND (((X5-X1)- 06111700
|
||||
UT[I-1].DEND-1) LEQ FACTOR)) THEN GO SQIT; 06111800
|
||||
END; 06111900
|
||||
IF USE!0 THEN % FUOND A POSSIBLE SQUASH SITUATION 06112000
|
||||
BEGIN 06112100
|
||||
IF INUSEOK THEN MOVEANDFIX; 06112200
|
||||
GO AGAIN; 06112300
|
||||
END ELSE % TIME TO WRAP IT UP FOR THIS EU UNLESS.... 06112400
|
||||
IF CONFLICT THEN IF NOT PASSTWO THEN % ..CONFLICTS EXIST 06112500
|
||||
BEGIN 06112600
|
||||
PASSTWO:=TRUE; 06112700
|
||||
GO AGAIN; 06112800
|
||||
END ELSE 06112900
|
||||
BEGIN % CLEAN-UP PASS AFTER CONFLICTS RESOLVED. 06113000
|
||||
PASSTWO:=CONFLICTS:=0; 06113100
|
||||
GO AGAIN; 06113200
|
||||
END; 06113300
|
||||
STOPSQ: FOR I:=D STEP 1 UNTIL S DO UT[I]:=ABS(P(DUP.LOD)&0[2:2:1]); 06113400
|
||||
IF NOT EUNOTSQUASHED THEN 06113500
|
||||
$ SET OMIT = NOT SHAREDISK 06113600
|
||||
DISKWAIT( R,AVSIZ,DISKAV); 06114300
|
||||
FORGETSPACE(R); 06114400
|
||||
P(1); SQUASHMESS; 06114500
|
||||
STOPIT: IF STOP THEN GO OUT; % STOPCK GOT US HERE 06114600
|
||||
END EU LOOP; 06114700
|
||||
OUT: 06114800
|
||||
FORGETSPACE(A1); FORGETSPACE(A2); FORGETSPACE(A3); 06114900
|
||||
$ SET OMIT = NOT SHAREDISK 06115000
|
||||
SDXIT: 06115500
|
||||
FORGETSPACE(A4); FORGETSPACE(A5); 06115600
|
||||
CELL:=PRTVALUE; 06115700
|
||||
STREAM(A:=BUFF.[15:15]-1); DS:=13 LIT" END SQUASH.~"; 06115800
|
||||
SPOUT(BUFF.[15:15]-1); 06115900
|
||||
$ SET OMIT = SHAREDISK 06115990
|
||||
UNLOCKDIRECTORY; 06116000
|
||||
$ POP OMIT 06116010
|
||||
UNLOCKTOG(USERDISKMASK); 06116100
|
||||
NOPROCESSTOG:=NOPROCESSTOG-1; 06116200
|
||||
KILL([MSCW]); 06116300
|
||||
END SQUASHING; 06116400
|
||||
PROCEDURE CHANGEABORT(X); VALUE X; REAL X; FORWARD;% 06179000
|
||||
REAL LOOKQ; 06179200
|
||||
PROCEDURE SIGNOFF(VECTOR,FILEBLOCK,PKT); 06180000
|
||||
VALUE VECTOR,FILEBLOCK,PKT; 06181000
|
||||
ARRAY VECTOR[*],FILEBLOCK[*];% 06182000
|
||||
REAL PKT; 06182100
|
||||
BEGIN ARRAY NAME LOG; 06183000
|
||||
INTEGER N,L,I,J,TIMEX;% 06184000
|
||||
INTEGER MIX; 06184100
|
||||
$ SET OMIT = NOT STATISTICS 06184199
|
||||
REAL TIMEAX,T,A,Q,ESED; 06185000
|
||||
$ SET OMIT = NOT(PACKETS) 06185099
|
||||
REAL UNITNO; 06185100
|
||||
INTEGER ARRAY PM[*]; 06185105
|
||||
$ POP OMIT 06185110
|
||||
$ SET OMIT = NOT(WORKSET AND WORKSETMONITOR) 06185111
|
||||
REAL DD; 06185112
|
||||
$ POP OMIT % WORKSET AND WORKSETMONITOR 06185113
|
||||
SUBROUTINE TIMEIT;% 06186000
|
||||
BEGIN CHANGEABORT(0);% 06187000
|
||||
WHILE (NT2:=XCLOCK+P(RTR)) GEQ WITCHINGHOUR DO 06188000
|
||||
MIDNIGHT; 06188100
|
||||
LOG[TIMEAX+2] ~ NT2;% 06189000
|
||||
$ SET OMIT = NOT(STATISTICS) 06189099
|
||||
STOPLOG(P1MIX,0); 06190000
|
||||
MIX~P1MIX; P1MIX~0; 06190100
|
||||
IDLETIME;% 06191000
|
||||
OLDIDLETIME ~ (LOG[TIMEX] ~ VECTOR[3]+% 06192000
|
||||
PROCTIME[MIX])+OLDIDLETIME; 06193000
|
||||
PROCTIME[MIX] ~ -VECTOR[3];% %127-06193500
|
||||
LOG[TIMEX+1]~VECTOR[4]+IOTIME[MIX]; 06194000
|
||||
$ SET OMIT = NOT WORKSET 06194890
|
||||
LOG[TIMEX+2] ~ OLAYTIME[MIX]; %710-06194900
|
||||
$ SET OMIT = WORKSET%710-06194990
|
||||
$ SET OMIT = NOT(WORKSET AND WORKSETMONITOR) 06195090
|
||||
IF WKSETMONITOR AND (DD=0) THEN 06195095
|
||||
BEGIN 06195100
|
||||
|
||||
@@ -2,17 +2,16 @@
|
||||
* retro-b5500/emulator B5500Processor.js
|
||||
************************************************************************
|
||||
* Copyright (c) 2012, Nigel Williams and Paul Kimpel.
|
||||
* Licensed under the MIT License, see http://www.opensource.org/licenses/mit-license.php
|
||||
* MIT Licensed http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* JavaScript object definition for the B5500 Processor (CPU) module.
|
||||
* B5500 Processor (CPU) module.
|
||||
************************************************************************
|
||||
* 2012-06-03 P.Kimpel
|
||||
* Original version, from thin air.
|
||||
***********************************************************************/
|
||||
"use strict";
|
||||
|
||||
/**************************************/
|
||||
function B5500Processor() {
|
||||
/* Constructor for the Processor module object */
|
||||
|
||||
this.scheduler = null; // Reference to current setTimeout id
|
||||
this.accessor = { // Memory access control block
|
||||
@@ -20,24 +19,21 @@ function B5500Processor() {
|
||||
word: 0, // 48-bit data word
|
||||
MAIL: 0, // Truthy if attempt to access @000-@777 in normal state
|
||||
MPED: 0, // Truthy if memory parity error
|
||||
MAED: 0}; // Truthy if memory address/inhibit error
|
||||
|
||||
MAED: 0 // Truthy if memory address/inhibit error
|
||||
};
|
||||
this.schedule.that = this; // Establish context for when called from setTimeout()
|
||||
|
||||
this.clear(); // Create and initialize the processor state
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
|
||||
B5500Processor.timeSlice = 5000; // Standard run() timeslice, about 5ms (we hope)
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.clear = function() {
|
||||
/* Initializes the processor state */
|
||||
/* Initializes the processor state, FF is FlipFlop (in modern parlance: boolean flag) */
|
||||
|
||||
this.A = 0; // Top-of-stack register 1
|
||||
this.AROF = 0; // A contents valid
|
||||
this.B = 0; // Top-of-stack register 2
|
||||
this.A = 0; // Top-of-stack register A
|
||||
this.AROF = 0; // A Register Occupied Flip-flop
|
||||
this.B = 0; // Top-of-stack register B
|
||||
this.BROF = 0; // B contents valid
|
||||
this.C = 0; // Current program instruction word address
|
||||
this.CCCF = 0; // Clock-count control FF (maintenance only)
|
||||
@@ -79,15 +75,15 @@ B5500Processor.prototype.clear = function() {
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.access = function(eValue) {
|
||||
B5500Processor.prototype.access = function(cc, eValue) {
|
||||
/* Access memory based on the E register. If the processor is in normal
|
||||
state, it cannot access the first 512 words of memory => invalid address */
|
||||
|
||||
this.E = eValue; // Just to show the world what's happening
|
||||
this.accessor.MAIL = (addr < 0x0200 && this.NCSF);
|
||||
this.accessor.MAIL = (this.addr < 0x0200 && this.NCSF);
|
||||
switch (eValue) {
|
||||
case 0x02: // A = [S]
|
||||
this.accessor.addr = this.S;
|
||||
@@ -145,11 +141,11 @@ B5500Processor.prototype.access = function(eValue) {
|
||||
this.PROF = 1;
|
||||
break;
|
||||
default:
|
||||
throw "Invalid E register value: " + eReg.toString(2);
|
||||
throw "Invalid E register value: " + this.E.toString(2);
|
||||
break;
|
||||
}
|
||||
|
||||
this.cycleCount += 6; // assume 6 us memory cycle time
|
||||
this.cycleCount += 6; // assume 6 us memory cycle time (the other option was 4 usec)
|
||||
if (this.accessor.MAED) {
|
||||
this.I |= 0x02; // set I02F - memory address/inhibit error
|
||||
if (this.NCSF || this !== cc.P1) {
|
||||
@@ -165,16 +161,18 @@ B5500Processor.prototype.access = function(eValue) {
|
||||
this.busy = false; // P1 memory parity in control state stops the proc
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.adjustAEmpty = function() {
|
||||
/* Adjusts the A register so that it is empty pushing the prior
|
||||
contents of A into B and B into memory, as necessary. */
|
||||
B5500Processor.prototype.adjustAEmpty = function(cc) {
|
||||
/*
|
||||
Adjusts the A register so that it is empty pushing the prior
|
||||
contents of A into B and B into memory, as necessary.
|
||||
*/
|
||||
|
||||
if (this.AROF} {
|
||||
if (this.AROF) {
|
||||
if (this.BROF) {
|
||||
if ((this.S >>> 6) == this.R || !this.NCSF) {
|
||||
if ((this.S >>> 6) === this.R || !this.NCSF) {
|
||||
this.I |= 0x04; // set I03F: stack overflow
|
||||
cc.signalInterrupt();
|
||||
} else {
|
||||
@@ -187,7 +185,7 @@ B5500Processor.prototype.adjustAEmpty = function() {
|
||||
this.BROF = 1;
|
||||
// else we're done -- A is already empty
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.adjustAFull = function() {
|
||||
@@ -205,15 +203,15 @@ B5500Processor.prototype.adjustAFull = function() {
|
||||
}
|
||||
// else we're done -- A is already full
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.adjustBEmpty = function() {
|
||||
B5500Processor.prototype.adjustBEmpty = function(cc) {
|
||||
/* Adjusts the B register so that it is empty pushing the prior
|
||||
contents of B into memory, as necessary. */
|
||||
|
||||
if (this.BROF) {
|
||||
if ((this.S >>> 6) = this.R || !this.NCSF) {
|
||||
if ((this.S >>> 6) === this.R || !this.NCSF) {
|
||||
this.I |= 0x04; // set I03F: stack overflow
|
||||
cc.signalInterrupt();
|
||||
} else {
|
||||
@@ -222,7 +220,7 @@ B5500Processor.prototype.adjustBEmpty = function() {
|
||||
}
|
||||
// else we're done -- B is already empty
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.adjustBFull = function() {
|
||||
@@ -234,10 +232,10 @@ B5500Processor.prototype.adjustBFull = function() {
|
||||
this.S--;
|
||||
// else we're done -- B is already full
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.exchangeTOS() {
|
||||
B5500Processor.prototype.exchangeTOS = function() {
|
||||
/* Exchanges the two top-of-stack values */
|
||||
var temp;
|
||||
|
||||
@@ -269,10 +267,10 @@ B5500Processor.prototype.exchangeTOS() {
|
||||
this.S--;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.storeForInterrupt = function(forTest) {
|
||||
B5500Processor.storeForInterrupt = function(cc, forTest) {
|
||||
/* Implements the 3011=SFI operator and the parts of SFT that are
|
||||
common to it. "forTest" implies use from SFT */
|
||||
var forced = this.Q & 0x0040; // Q07F: Hardware-induced SFI syllable
|
||||
@@ -296,9 +294,7 @@ B5500Processor.storeForInterrupt = function(forTest) {
|
||||
this.S++;
|
||||
this.access(0x0B); // [S] = B
|
||||
}
|
||||
this.B = this.X + // store CM loop-control word
|
||||
saveAROF * 0x200000000000 +
|
||||
0xC00000000000;
|
||||
this.B = this.X + saveAROF * 0x200000000000 + 0xC00000000000; // store CM loop-control word
|
||||
this.S++;
|
||||
this.access(0x0B); // [S] = B
|
||||
} else {
|
||||
@@ -355,7 +351,7 @@ B5500Processor.storeForInterrupt = function(forTest) {
|
||||
this.TM = 0;
|
||||
this.MROF = 0;
|
||||
this.MWOF = 0;
|
||||
}
|
||||
}
|
||||
|
||||
this.M = (this.R*64) + 0x08; // store initiate word at R+@10
|
||||
this.access(0x0D); // [M] = B
|
||||
@@ -377,7 +373,7 @@ B5500Processor.storeForInterrupt = function(forTest) {
|
||||
cc.HP2F = 1;
|
||||
cc.P2BF = 0;
|
||||
if (cc.P2.scheduler) {
|
||||
cancelTimeout(cc.P2.scheduler);
|
||||
cc.cancelTimeout(cc.P2.scheduler);
|
||||
cc.P2.scheduler = null;
|
||||
}
|
||||
}
|
||||
@@ -401,12 +397,12 @@ B5500Processor.storeForInterrupt = function(forTest) {
|
||||
cc.HP2F = 1;
|
||||
cc.P2BF = 0;
|
||||
if (cc.P2.scheduler) {
|
||||
cancelTimeout(cc.P2.scheduler);
|
||||
cc.cancelTimeout(cc.P2.scheduler);
|
||||
cc.P2.scheduler = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.initiate = function(forTest) {
|
||||
@@ -503,10 +499,10 @@ B5500Processor.initiate = function(forTest) {
|
||||
this.NCSF = 1;
|
||||
this.busy = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.computeRelativeAddr(offset, cEnabled) {
|
||||
B5500Processor.prototype.computeRelativeAddr = function(offset, cEnabled) {
|
||||
/* Computes an absolute memory address from the relative "offset" parameter
|
||||
and leaves it in the M register. See Table 6-1 in the B5500 Reference
|
||||
Manual. "cEnable" determines whether C-relative addressing is permitted.
|
||||
@@ -550,10 +546,10 @@ B5500Processor.prototype.computeRelativeAddr(offset, cEnabled) {
|
||||
} else {
|
||||
this.M = (this.R*64) + (offset & 0x3FF);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.indexDescriptor() {
|
||||
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
|
||||
to be exited */
|
||||
@@ -575,7 +571,7 @@ B5500Processor.prototype.indexDescriptor() {
|
||||
do {
|
||||
xo = xm % 8;
|
||||
xm = (xm - xo)/8;
|
||||
this.cycleCount++
|
||||
this.cycleCount++;
|
||||
} while (--xe > 0);
|
||||
if (xo >= 4) {
|
||||
xm++;
|
||||
@@ -618,21 +614,21 @@ B5500Processor.prototype.indexDescriptor() {
|
||||
}
|
||||
|
||||
return interrupted;
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.buildMSCW();
|
||||
B5500Processor.prototype.buildMSCW = function() {
|
||||
/* Return a Mark Stack Control Word from current processor state */
|
||||
|
||||
return this.F * 0x8000 +
|
||||
this.SALF * 0x40000000 +
|
||||
this.MSFF * 0x80000000 +
|
||||
this.R * 0x200000000 +
|
||||
0xC00000000000;
|
||||
}
|
||||
return this.F * 0x8000 +
|
||||
this.SALF * 0x40000000 +
|
||||
this.MSFF * 0x80000000 +
|
||||
this.R * 0x200000000 +
|
||||
0xC00000000000;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.enterSubroutine(descriptorCall) {
|
||||
B5500Processor.prototype.enterSubroutine = function(cc, descriptorCall) {
|
||||
/* Enters a subroutine via the present program descriptor in A as part
|
||||
of an OPDC or DESC syllable. Also handles accidental entry */
|
||||
var aw = this.A; // local copy of word in A reg
|
||||
@@ -690,13 +686,15 @@ B5500Processor.prototype.enterSubroutine(descriptorCall) {
|
||||
this.S = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.operandCall() {
|
||||
/* OPDC, the moral equivalent of "load accumulator" on lesser
|
||||
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 */
|
||||
B5500Processor.prototype.operandCall = function() {
|
||||
/*
|
||||
OPDC, the moral equivalent of "load accumulator" on lesser
|
||||
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
|
||||
|
||||
@@ -749,14 +747,16 @@ B5500Processor.prototype.operandCall() {
|
||||
this.SALF = 1;
|
||||
this.VARF = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.descriptorCall() {
|
||||
/* DESC, the moral equivalent of "load address" on lesser
|
||||
machines. Assumes the syllable has already loaded a word into A, and
|
||||
that the address of that word is in M.
|
||||
See Figures 6-2, 6-3, and 6-4 in the B5500 Reference Manual */
|
||||
B5500Processor.prototype.descriptorCall = function() {
|
||||
/*
|
||||
DESC, the moral equivalent of "load address" on lesser
|
||||
machines. Assumes the syllable has already loaded a word into A, and
|
||||
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
|
||||
|
||||
@@ -804,15 +804,17 @@ B5500Processor.prototype.descriptorCall() {
|
||||
this.SALF = 1;
|
||||
this.VARF = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.run = function() {
|
||||
/* Instruction execution driver for the B5500 processor. This function is
|
||||
an artifact of the emulator design and does not represent any physical
|
||||
process or state of the processor. This routine assumes the registers are
|
||||
set up, and in particular a syllable is in T with TROF set. It will run
|
||||
until cycleCount >= cycleLimit or !this.busy */
|
||||
/*
|
||||
Instruction execution driver for the B5500 processor. This function is
|
||||
an artifact of the emulator design and does not represent any physical
|
||||
process or state of the processor. This routine assumes the registers are
|
||||
set up, and in particular a syllable is in T with TROF set. It will run
|
||||
until cycleCount >= cycleLimit or !this.busy
|
||||
*/
|
||||
var opcode;
|
||||
var t1;
|
||||
var t2;
|
||||
@@ -1513,20 +1515,22 @@ B5500Processor.prototype.run = function() {
|
||||
}
|
||||
}
|
||||
} while ((this.cycleCount += 2) < this.cycleLimit && this.busy);
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.schedule = function schedule() {
|
||||
/* Schedules the processor run time and attempts to throttle performance
|
||||
to approximate that of a real B5500. Well, at least we hope this will run
|
||||
fast enough that the performance will need to be throttled. It establishes
|
||||
a timeslice in terms of a number of processor "cycles" of 1 microsecond
|
||||
each and calls run() to execute at most that number of cycles. run()
|
||||
counts up cycles until it reaches this limit or some terminating event
|
||||
(such as a halt), then exits back here. If the processor remains active,
|
||||
this routine will reschedule itself for an appropriate later time, thereby
|
||||
throttling the performance and allowing other modules a chance at the
|
||||
Javascript execution thread. */
|
||||
/*
|
||||
Schedules the processor run time and attempts to throttle performance
|
||||
to approximate that of a real B5500. Well, at least we hope this will run
|
||||
fast enough that the performance will need to be throttled. It establishes
|
||||
a timeslice in terms of a number of processor "cycles" of 1 microsecond
|
||||
each and calls run() to execute at most that number of cycles. run()
|
||||
counts up cycles until it reaches this limit or some terminating event
|
||||
(such as a halt), then exits back here. If the processor remains active,
|
||||
this routine will reschedule itself for an appropriate later time, thereby
|
||||
throttling the performance and allowing other modules a chance at the
|
||||
Javascript execution thread.
|
||||
*/
|
||||
var delayTime;
|
||||
var that = schedule.that;
|
||||
|
||||
@@ -1543,4 +1547,4 @@ B5500Processor.prototype.schedule = function schedule() {
|
||||
that.scheduleSlack += delayTime;
|
||||
that.scheduler = setTimeout(that.schedule, (delayTime < 0 ? 0 : delayTime));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@ function B5500DDLamp(x, y) {
|
||||
|
||||
/**************************************/
|
||||
|
||||
B5500DDLamp.onColor = "#FF9933";
|
||||
B5500DDLamp.onColor = "#FF9900";
|
||||
B5500DDLamp.offColor = "#999999";
|
||||
|
||||
/**************************************/
|
||||
@@ -193,7 +193,7 @@ B5500DDRegister.prototype.update = function(value) {
|
||||
var bit;
|
||||
var mask = value % 0x1000000000000;
|
||||
|
||||
while (mask) {
|
||||
while (bitNr < this.bits) {
|
||||
bitNr++;
|
||||
bit = mask % 2;
|
||||
this.lamps[bitNr].element.style.backgroundColor = (bit ? B5500DDLamp.onColor : B5500DDLamp.offColor);
|
||||
|
||||
@@ -16,17 +16,19 @@ var nextRefresh = 0;
|
||||
var panel;
|
||||
var refreshTimer = null;
|
||||
var totalDelay = 0;
|
||||
var totalIdle = 0;
|
||||
var totalTime = 0;
|
||||
|
||||
var updateDisplay = function updateDisplay() {
|
||||
/* Schedules itself to update the display on a periodic basis. */
|
||||
var thisTime = new Date().getTime();
|
||||
var delta;
|
||||
var idle;
|
||||
var meter = document.getElementById("idleMeter");
|
||||
var that = updateDisplay.that;
|
||||
|
||||
panel.X.update(Math.random()*0x8000000000);
|
||||
panel.A.update(Math.random()*0x1000000000000);
|
||||
panel.A.update((Math.random()/65536+Math.random())*0x1000000000000);
|
||||
panel.B.update(Math.random()*0x1000000000000);
|
||||
panel.P.update(Math.random()*0x1000000000000);
|
||||
panel.J.update(Math.random()*0x10);
|
||||
@@ -58,7 +60,9 @@ var updateDisplay = function updateDisplay() {
|
||||
refreshTimer = setTimeout(updateDisplay, (delta < 0 ? (delta=0) : delta));
|
||||
totalTime = (totalTime*99 + displayRefreshPeriod)/100;
|
||||
totalDelay = (totalDelay*99 + delta)/100;
|
||||
meter.value = (totalDelay/totalTime*100).toFixed(1) + "%";
|
||||
idle = nextRefresh-new Date().getTime();
|
||||
totalIdle = (totalIdle*99 + (idle < 0 ? 0 : idle))/100;
|
||||
meter.value = (totalIdle/totalTime*100).toFixed(1) + "%";
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
|
||||
Reference in New Issue
Block a user