1
0
mirror of https://github.com/pkimpel/retro-b5500.git synced 2026-04-18 10:06:01 +00:00

1. Commit emulator files at the point where the Mark XIII MCP appears to be able to initialization.

2. Fix character-mode B-register handling in Processor and slightly optimize some stream syllables.
2. Fix I/O-finished interrupt signaling (or rather, the lack thereof) in IOUnit.
3. Change system option settings in ColdLoader based on recent MCP tests.
4. Commit minor improvements to SyllableDebugger.
5. Commit version of KERNEL object code for use with SyllableDebugger.
6. Commit Mark XVI DCMCP transcription as of 2013-03-17.
This commit is contained in:
paul.kimpel@digm.com
2013-03-18 16:10:48 +00:00
parent 041a114abc
commit 1c3c8ae307
9 changed files with 481 additions and 165 deletions

View File

@@ -22435,3 +22435,160 @@ WHY: BEGIN FILEMESS("#NO FIL",IF MID.UNITNUM!0 THEN %148-37224000
FID:=LABELTABLE[U].[6:42]; 37236750
END; 37237000
END; 37238000
REPLY[P1MIX]:=0; 37239000
END;% 37240000
IF COUNT {0 THEN GO TO START; %120-37240050
IF COUNT>1 THEN 37240100
SXIT: BEGIN FILEMESS("#DUP ","FIL ",MID,FID,REEL,CDATE,CYCLE); 37240200
WHILE (COUNT~COUNT-1)}0 DO 37240300
BEGIN IF (U~P)<16 THEN IF MID!0 THEN 37240400
IF (T1~PRNTABLE[U].[15:15])!0 THEN 37240500
FILECLOSE(T1&@12[18:33:15]); 37240600
STREAM(X~[TINU[U]]:D~S~SPACE(10)); 37240700
BEGIN SI~X; SI~SI+5; DS~8 LIT " DUP ON "; 37240800
DS~3 CHR; DS~LIT "~"; 37240900
X~DI; 37240910
END; 37241000
T1~P; 37241010
IF U}32 THEN IF CIDROW[U -32]!0 THEN 37241020
STREAM(DK~CIDTABLE[U -32,2],T1); 37241030
BEGIN DI~DI-1; DS~6 LIT ",DECK "; 37241040
SI~LOC DK; SI~SI+1; DS~7 CHR; 37241050
END; 37241060
SPOUT(5); 37241100
END; 37241200
REPLY[P1MIX]:= -VWY&VOK[36:42:6]&VIL[30:42:6]; 37241300
COMPLEXSLEEP(DSED OR (REPLY[P1MIX]>0)); 37241400
CHECKTERMIX; 37241500
IF (T1:=REPLY[P1MIX]).[33:15]=VIL THEN 37241510
BEGIN REPLY[P1MIX]~0; 37241520
IF T1.[FF] > 64 THEN GO SXIT; 37241525
P(T1.[18:15]); 37241530
GO TO X; 37241540
END; 37241550
IF NOT WHYSLEEP(VWY&VOK[36:42:6]&VIL[30:42;6]) THEN 37241600
BEGIN S:=SEARCH;GO SXIT END; 37241610
Y: REPLY[P1MIX]:=0; GO TO START; 37241700
END; 37241800
X: 37241810
LABELTABLE[U~P].[1:5]~@20; 37241900
IF NOT UNLABELED THEN 37242000
BEGIN FPB:=PRT[P1MIX,3]; 37242100
FPB[FN]:=MID; 37242200
FPB[FN+1]:=FID; 37242300
END; 37242400
IF U LSS 16 THEN 37242600
IF MID!0 THEN 37242800
BEGIN IF (T1!PRNTABLE[U].[15:15])!0 THEN% 37243000
BEGIN FILECLOSE(T1&3[18:33:15]);% 37244000
M[M[T1-3] INX 5].[39:4]~1;% 37245000
END;% 37246000
RRRMECH~TWO(U) OR RRRMECH; STARTIMING(FN,U); 37248000
IF UNLABELED OR IL OR CYCLE.[1:1] THEN GO EXIT; 37248500
T1 ~ SPACE(11)&10[8:38:10]&MODE[21:47:1]% 37249000
&3[23:46:2];% 37250000
LO~@40; FIRST~1;% 37251000
READALABEL: IF REED ! 0 THEN IF FIRST THEN% 37252000
REW: BEGIN FIRST~WAITIO(@4200000000,0,U); GO READALABEL END ELSE 37253000
BEGIN SETNOTINUSE(U,I); FORGETSPACE(T1.[33:15]); 37254000
STOPTIMING(FN,1023); GO TO START END; 37255000
STREAM(Y:=0:X:=0,T1); 37255100
BEGIN DI:=LOC X; DS:=8 LIT "VOL1HDR1"; 37255200
SI:=T1; DI:=DI-8; 37255300
IF 4 SC=DC THEN TALLY:=1 ELSE 37255400
BEGIN SI:=T1; IF 4 SC=DC THEN TALLY:=2; END; 37255500
Y:=TALLY; 37255700
END; 37255800
IF(USASI:=P)>0 THEN USASITAPE(T1.[CF],USASI,2,U,0); 37255900
STREAM(M~0,F~0,R~0,D~0,C~0:S~T1 INX 1);% 37256000
BEGIN SI~S; SI~LOC M; DS~2 WDS; DS~3 OCT;% 37257000
DS:=5 OCT;DS:=2 OCT; 37258000
END;% 37259000
IF (P=CYCLE OR CYCLE=0) AND (P(XCH)=CDATE OR CDATE=0) AND% 37260000
(P(XCH)=REEL OR REEL=0)AND ((P(XCH) EQV FID)=NOT 0) AND% 37261000
((P(XCH) EQV MID)=NOT 0) THEN% 37262000
BEGIN FORGETSPACE(T1.[33:15]); T1~@340000005;% 37263000
LO~0;T1~REED; GO TO EXIT;% 37264000
END;% 37265000
IF FIRST THEN GO REW;% 37266000
LO:=@60; DO UNTIL (FIRST:=REED).[42:1]; DO UNTIL REED.[42:1]; 37267000
IF USASI>0 THEN DO UNTIL REED.[42:1] ELSE FIRST:=REED; 37267050
LO~@40; GO READALABEL; 37267100
END;% 37268000
EXIT: FINDINPUT~U;% 37269000
END FINDINPUT;% 37270000
PROCEDURE STARTIMING(FN,U); VALUE FN,U; REAL FN,U;% 37271000
BEGIN ARRAY FPB[*]; INTEGER I,J;% 37272000
FPB~PRT[P1MIX,3];% 37273000
IF U<32 THEN 37273100
BEGIN IF FPB[FN+4]}0 THEN 37274000
BEGIN IF (I+FPB[FN+3].[36:6])!0 THEN% 37275000
IF I NEQ U+1 OR FPB[FN+2].[8:10] NEQ RDCTABLE[U].[14:10] 37276000
THEN 37276010
IF (I~FPB.[8:10])<(1023-ETRLNG) THEN 37276100
BEGIN J~GETSPACE(I+ETRLNG,2,1)+2;% 37277000
$ SET OMIT = SHAREDISK 37277999
MOVE(I,FPB,J);% 37278000
$ POP OMIT 37278001
$ SET OMIT = NOT SHAREDISK 37278099
MOVE(ETRLNG,[FPB[FN]],J+I);% 37278200
FORGETSPACE(FPB.[33:15]);% 37279000
NFO[(P1MIX-1)|NDX]~ 37279100
PRT[P1MIX,3]~FPB~[M[J]]&(I+ETRLNG)[8:38:10];% 37280000
FPB[FN+4]+0; FPB[FN+3].[24:12]~0;% 37281000
END;% 37282000
FPB[FN+4]~FPB[FN+4]-CLOCK-P(RTR);% 37283000
FPB[FN+3].[36:6]~U+1;% 37284000
IF U LSS 16 THEN% RDC & PRN LOG ENTRIES 37284100
BEGIN ; 37284110
STREAM(R:=RDCTABLE[U].[14:10],D:=RDCTABLE[U].[24:17], 37284120
C:=RDCTABLE[U].[41:7],T:=[FPB[FN +2]]); 37284130
BEGIN SI:=LOC R;DS:=3DEC;DS:=5DEC;DS:=DEC END; 37284140
FPB[FN +3].[6:17]:=PRNTABLE[U].[31;17]; 37284150
END; 37284310
END END ELSE 37285000
BEGIN IF (I:=FPB[FN+4]) LSS 0 THEN 37285100
BEGIN FPB[FN+4]~I+CLOCK+P(RTR); I~FPB[FN+3].[36:6]-1; 37285200
FPB[FN+3].[24:12]~P(DUP).[24:12]+(J~TINU[I].[18:12]); 37285300
IF I<16 THEN 37285305
IF J>0 THEN FILEMESS("# IO"&TINU[I] 37285310
[12:30:18],-RETRIES",FPB[FN],FPB[FN+1],J,0,0); %715-37285320
TINU[I].[18:12]~0; 37285400
END END END TIMING; 37285500
REAL PROCEDURE DISKADDRESS(MID,FID,FPB3,A,H,IO); % (SHM)37286000
VALUE MID,FID,FPB3,A,H,IO; % (SHM)37286100
REAL MID,FID,FPB3,A,IO; % (SHM)37286200
ARRAY H[*]; 37286300
BEGIN LABEL EOF, EOF2; 37287000
INTEGER I; 37287250
REAL T, V; 37287500
IF A}0 THEN% 37288000
BEGIN T~(A DIV H[0].[30:12])|H[0].[42:6];% 37289000
IF H[9] LEQ I:=(IF H[1]=0 THEN 0 ELSE T DIV H[1]) THEN 37290000
GO TO EOF; 37290100
IF H[I:=I+10]=0 THEN % NEW ROW NEEDED. 37291000
IF IO THEN GO TO EOF ELSE % EOF ON A READ. 37291200
IF IO=2 THEN % CALLED FROM FILEOPEN SO 37291400
BEGIN % DONT EXPAND THE FILE YET. 37291600
T:=1; 37291800
GO TO EOF2; 37292000
END 37292200
ELSE 37292400
IF H[4] THEN % IN DIRECTORY, UPDATE HEADER. 37292600
P(DIRECTORYSEARCH(-MID,FID,-H&I[CTF]),DEL) 37292800
ELSE % NOT IN DIREECTORY. 37293000
BEGIN % (SHM)37293010
IF (V:=FPB3.[18:5]) GTR 0 THEN % EU SPECIFIED % (SHM)37293020
V:=(IF V GTR 20 THEN 0 ELSE -V) ELSE % (SHM)37293030
IF (V:=FPB3.[16:2]) GTR 0 THEN % SPEED SPECIFIED %(SHM)37293040
V:=(IF V GTR 2 THEN 0 ELSE V) ELSE % (SHM)37293050
V:=0; % NO SPEED OR EU SPECIFIED % (SHM)37293060
H[I] := PETUSERDISK(H[8],V); % (SHM)37293070
END; % (SHM)37293330
T~H[I]+I~T MOD H[1];% 37294000
STREAM(D~[T]); BEGIN SI~D; DS~8 DEC END;% 37295000
END ELSE% 37296000
EOF: T~0;% 37297000
EOF2: 37297500
DISKADDRESS~T;% 37298000
END DISKADDRESS;% 37299000

View File

@@ -42,7 +42,7 @@ function B5500CentralControl() {
// Instance variables and flags
this.poweredUp = 0; // System power indicator
this.unitStatusMask = 0; // Peripheral unit ready-status bitmask
this.unitStatusMask = 0; // Peripheral unit ready-status bitmask
this.unitBusyMask = 0; // Peripheral unit busy-status bitmask
this.PB1L = 0; // 0=> PA is P1, 1=> PB is P1
@@ -61,92 +61,92 @@ function B5500CentralControl() {
/**************************************/
/* Global constants */
B5500CentralControl.version = "0.01";
B5500CentralControl.version = "0.02";
B5500CentralControl.rtcTick = 1000/60; // Real-time clock period, milliseconds
B5500CentralControl.pow2 = [ // powers of 2 from 0 to 52
0x1, 0x2, 0x4, 0x8,
0x10, 0x20, 0x40, 0x80,
0x100, 0x200, 0x400, 0x800,
0x1000, 0x2000, 0x4000, 0x8000,
0x10000, 0x20000, 0x40000, 0x80000,
0x100000, 0x200000, 0x400000, 0x800000,
0x1000000, 0x2000000, 0x4000000, 0x8000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000,
0x100000000, 0x200000000, 0x400000000, 0x800000000,
0x1000000000, 0x2000000000, 0x4000000000, 0x8000000000,
0x10000000000, 0x20000000000, 0x40000000000, 0x80000000000,
0x100000000000, 0x200000000000, 0x400000000000, 0x800000000000,
0x1000000000000, 0x2000000000000, 0x4000000000000, 0x8000000000000,
0x1, 0x2, 0x4, 0x8,
0x10, 0x20, 0x40, 0x80,
0x100, 0x200, 0x400, 0x800,
0x1000, 0x2000, 0x4000, 0x8000,
0x10000, 0x20000, 0x40000, 0x80000,
0x100000, 0x200000, 0x400000, 0x800000,
0x1000000, 0x2000000, 0x4000000, 0x8000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000,
0x100000000, 0x200000000, 0x400000000, 0x800000000,
0x1000000000, 0x2000000000, 0x4000000000, 0x8000000000,
0x10000000000, 0x20000000000, 0x40000000000, 0x80000000000,
0x100000000000, 0x200000000000, 0x400000000000, 0x800000000000,
0x1000000000000, 0x2000000000000, 0x4000000000000, 0x8000000000000,
0x10000000000000];
B5500CentralControl.mask2 = [ // (2**n)-1 For n From 0 to 52
0x0, 0x1, 0x3, 0x7,
0x0F, 0x1F, 0x3F, 0x7F,
0x0FF, 0x1FF, 0x3FF, 0x7FF,
0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF,
0x0FFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF,
0x0FFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,
0x0FFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF,
0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF,
0x0FFFFFFFF, 0x1FFFFFFFF, 0x3FFFFFFFF, 0x7FFFFFFFF,
0x0FFFFFFFFF, 0x1FFFFFFFFF, 0x3FFFFFFFFF, 0x7FFFFFFFFF,
0x0FFFFFFFFFF, 0x1FFFFFFFFFF, 0x3FFFFFFFFFF, 0x7FFFFFFFFFF,
0x0FFFFFFFFFFF, 0x1FFFFFFFFFFF, 0x3FFFFFFFFFFF , 0x7FFFFFFFFFFF,
0x0FFFFFFFFFFFF, 0x1FFFFFFFFFFFF, 0x3FFFFFFFFFFFF, 0x7FFFFFFFFFFFF,
0x0, 0x1, 0x3, 0x7,
0x0F, 0x1F, 0x3F, 0x7F,
0x0FF, 0x1FF, 0x3FF, 0x7FF,
0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF,
0x0FFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF,
0x0FFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,
0x0FFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF,
0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF,
0x0FFFFFFFF, 0x1FFFFFFFF, 0x3FFFFFFFF, 0x7FFFFFFFF,
0x0FFFFFFFFF, 0x1FFFFFFFFF, 0x3FFFFFFFFF, 0x7FFFFFFFFF,
0x0FFFFFFFFFF, 0x1FFFFFFFFFF, 0x3FFFFFFFFFF, 0x7FFFFFFFFFF,
0x0FFFFFFFFFFF, 0x1FFFFFFFFFFF, 0x3FFFFFFFFFFF , 0x7FFFFFFFFFFF,
0x0FFFFFFFFFFFF, 0x1FFFFFFFFFFFF, 0x3FFFFFFFFFFFF, 0x7FFFFFFFFFFFF,
0x0FFFFFFFFFFFFF] ;
// The following two-dimensional array translates unit designates to a unique 1-relative
// peripheral unit index. This index is the same as the unit's ready-status bit number,
// which is why they are in the range 17..47. The [0] dimension determines the index
// when writing; the [1] dimension determines the index when reading. This approach
// is necessary since some unit designates map to two different devices depending
// The following two-dimensional array translates unit designates to a unique 1-relative
// peripheral unit index. This index is the same as the unit's ready-status bit number,
// which is why they are in the range 17..47. The [0] dimension determines the index
// when writing; the [1] dimension determines the index when reading. This approach
// is necessary since some unit designates map to two different devices depending
// on IOD.[24:1], e.g. designate 14=CPA/CRA (status bits 23/24).
B5500CentralControl.unitIndex = [
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[null, 47,null, 46, 31, 45, 29, 44, 30, 43, 25, 42, 28, 41,null, 40,
17, 39, 21, 38, 18, 37, 27, 36,null, 35, 26, 34,null, 33, 22, 32],
[null, 47,null, 46, 31, 45, 29, 44, 30, 43, 24, 42, 28, 41, 23, 40,
[null, 47,null, 46, 31, 45, 29, 44, 30, 43, 25, 42, 28, 41,null, 40,
17, 39, 21, 38, 18, 37, 27, 36,null, 35, 26, 34,null, 33, 22, 32],
[null, 47,null, 46, 31, 45, 29, 44, 30, 43, 24, 42, 28, 41, 23, 40,
17, 39, 20, 38, 19, 37,null, 36,null, 35,null, 34,null, 33, 22, 32]];
// The following object maps the unit mnemonics from B5500SystemConfiguration.units
// The following object maps the unit mnemonics from B5500SystemConfiguration.units
// to the attributes needed to configure the CC unit[] array.
B5500CentralControl.unitSpecs = {
SPO: {unitIndex: 22, designate: 30, unitClass: B5500SPOUnit},
DKA: {unitIndex: 29, designate: 6, unitClass: B5500DiskUnit},
DKB: {unitIndex: 28, designate: 12, unitClass: B5500DiskUnit},
CRA: {unitIndex: 24, designate: 10, unitClass: null},
CRB: {unitIndex: 23, designate: 14, unitClass: null},
CPA: {unitIndex: 25, designate: 10, unitClass: null},
LPA: {unitIndex: 27, designate: 22, unitClass: null},
LPB: {unitIndex: 26, designate: 26, unitClass: null},
PRA: {unitIndex: 20, designate: 18, unitClass: null},
PRB: {unitIndex: 19, designate: 20, unitClass: null},
PPA: {unitIndex: 21, designate: 18, unitClass: null},
PPB: {unitIndex: 18, designate: 20, unitClass: null},
DCA: {unitIndex: 17, designate: 16, unitClass: null},
DKA: {unitIndex: 29, designate: 6, unitClass: B5500DiskUnit},
DKB: {unitIndex: 28, designate: 12, unitClass: B5500DiskUnit},
CRA: {unitIndex: 24, designate: 10, unitClass: null},
CRB: {unitIndex: 23, designate: 14, unitClass: null},
CPA: {unitIndex: 25, designate: 10, unitClass: null},
LPA: {unitIndex: 27, designate: 22, unitClass: null},
LPB: {unitIndex: 26, designate: 26, unitClass: null},
PRA: {unitIndex: 20, designate: 18, unitClass: null},
PRB: {unitIndex: 19, designate: 20, unitClass: null},
PPA: {unitIndex: 21, designate: 18, unitClass: null},
PPB: {unitIndex: 18, designate: 20, unitClass: null},
DCA: {unitIndex: 17, designate: 16, unitClass: null},
DRA: {unitIndex: 31, designate: 4, unitClass: null},
DRB: {unitIndex: 30, designate: 8, unitClass: null},
MTA: {unitIndex: 47, designate: 1, unitClass: null},
MTB: {unitIndex: 46, designate: 3, unitClass: null},
MTC: {unitIndex: 45, designate: 5, unitClass: null},
MTD: {unitIndex: 44, designate: 7, unitClass: null},
MTE: {unitIndex: 43, designate: 9, unitClass: null},
MTF: {unitIndex: 42, designate: 11, unitClass: null},
MTH: {unitIndex: 41, designate: 13, unitClass: null},
MTJ: {unitIndex: 40, designate: 15, unitClass: null},
MTK: {unitIndex: 39, designate: 17, unitClass: null},
MTL: {unitIndex: 38, designate: 19, unitClass: null},
MTM: {unitIndex: 37, designate: 21, unitClass: null},
MTN: {unitIndex: 36, designate: 23, unitClass: null},
MTP: {unitIndex: 35, designate: 25, unitClass: null},
MTR: {unitIndex: 34, designate: 27, unitClass: null},
MTS: {unitIndex: 33, designate: 29, unitClass: null},
MTT: {unitIndex: 32, designate: 31, unitClass: null}};
MTA: {unitIndex: 47, designate: 1, unitClass: null},
MTB: {unitIndex: 46, designate: 3, unitClass: null},
MTC: {unitIndex: 45, designate: 5, unitClass: null},
MTD: {unitIndex: 44, designate: 7, unitClass: null},
MTE: {unitIndex: 43, designate: 9, unitClass: null},
MTF: {unitIndex: 42, designate: 11, unitClass: null},
MTH: {unitIndex: 41, designate: 13, unitClass: null},
MTJ: {unitIndex: 40, designate: 15, unitClass: null},
MTK: {unitIndex: 39, designate: 17, unitClass: null},
MTL: {unitIndex: 38, designate: 19, unitClass: null},
MTM: {unitIndex: 37, designate: 21, unitClass: null},
MTN: {unitIndex: 36, designate: 23, unitClass: null},
MTP: {unitIndex: 35, designate: 25, unitClass: null},
MTR: {unitIndex: 34, designate: 27, unitClass: null},
MTS: {unitIndex: 33, designate: 29, unitClass: null},
MTT: {unitIndex: 32, designate: 31, unitClass: null}};
/**************************************/
B5500CentralControl.prototype.clear = function() {
@@ -262,7 +262,7 @@ B5500CentralControl.prototype.fieldIsolate = function(word, start, width) {
/**************************************/
B5500CentralControl.prototype.fieldInsert = function(word, start, width, value) {
/* Inserts a bit field from the low-order bits of value ([48-width:width])
/* Inserts a bit field from the low-order bits of value ([48-width:width])
into word.[start:width] and returns the updated word */
var ue = 48-start; // word upper power exponent
var le = ue-width; // word lower power exponent
@@ -550,7 +550,7 @@ B5500CentralControl.prototype.tock = function tock() {
/**************************************/
B5500CentralControl.prototype.haltP2 = function() {
/* Called by P1 to halt P2. storeForInterrupt() will set P2BF=0 */
this.HP2F = 1;
// We know P2 is not currently running on this thread, so save its registers
if (this.P2 && this.P2BF) {
@@ -703,7 +703,7 @@ B5500CentralControl.prototype.loadComplete = function loadComplete() {
} else { // Nothing finished yet (or there was an error)
that.loadTimer = setTimeout(that.loadComplete, 100);
}
if (completed) {
that.loadTimer = null;
that.LOFF = 0;
@@ -771,7 +771,7 @@ B5500CentralControl.prototype.loadTest = function(buf, loadAddr) {
throw "cc.loadTest: Cannot load with system powered off"
} else {
while (bytes > 6) {
word = data.getUint8(x)* 0x10000000000 +
word = data.getUint8(x)* 0x10000000000 +
data.getUint8(x+1)* 0x100000000 +
data.getUint8(x+2)* 0x1000000 +
data.getUint8(x+3)* 0x10000 +
@@ -820,47 +820,47 @@ B5500CentralControl.prototype.configureSystem = function() {
var u;
var unitClass;
var x;
function makeChange(cc, maskBit) {
return function(ready) {
cc.unitStatusMask = (ready ? cc.bitSet(cc.unitStatusMask, maskBit)
: cc.bitReset(cc.unitStatusMask, maskBit));
};
}
function makeSignal(cc, mnemonic) {
switch (mnemonic) {
case "SPO":
return function() {
cc.CCI05F = 1;
cc.CCI05F = 1;
cc.signalInterrupt();
};
break;
case "LPA":
return function() {
cc.setUnitBusy(27, 0);
cc.CCI06F = 1;
cc.CCI06F = 1;
cc.signalInterrupt();
};
break;
case "LPB":
return function() {
cc.setUnitBusy(26, 0);
cc.CCI07F = 1;
cc.CCI07F = 1;
cc.signalInterrupt();
};
break;
case "DKA":
return function() {
cc.setUnitBusy(29, 0);
cc.CCI15F = 1;
cc.CCI15F = 1;
cc.signalInterrupt();
};
break;
case "DKB":
return function() {
cc.setUnitBusy(28, 0);
cc.CCI16F = 1;
cc.CCI16F = 1;
cc.signalInterrupt();
};
break;
@@ -892,7 +892,7 @@ B5500CentralControl.prototype.configureSystem = function() {
this.memMod[x] = new Float64Array(this.addressSpace[x]);
}
}
// Configure the peripheral units
for (mnem in cfg.units) {
if (cfg.units[mnem]) {
@@ -900,7 +900,7 @@ B5500CentralControl.prototype.configureSystem = function() {
if (specs) {
unitClass = specs.unitClass || B5500DummyUnit;
if (unitClass) {
u = new unitClass(mnem, specs.unitIndex, specs.designate,
u = new unitClass(mnem, specs.unitIndex, specs.designate,
makeChange(this, specs.unitIndex), makeSignal(this, mnem));
this.unit[specs.unitIndex] = u;
}

View File

@@ -528,15 +528,15 @@ B5500IOUnit.prototype.finish = function () {
break;
case "2":
this.store(0x0D);
this.cc.CCI08F = 1; // set I/O Finished #2
this.cc.CCI09F = 1; // set I/O Finished #2
break;
case "3":
this.store(0x0E);
this.cc.CCI08F = 1; // set I/O Finished #3
this.cc.CCI10F = 1; // set I/O Finished #3
break;
case "4":
this.store(0x0F);
this.cc.CCI08F = 1; // set I/O Finished #4
this.cc.CCI11F = 1; // set I/O Finished #4
break;
}

View File

@@ -645,7 +645,11 @@ B5500Processor.prototype.compareSourceWithDest = function(count) {
this.Q |= 0x08; // set Q04F so we won't store B anymore
}
this.S++;
this.loadBviaS(); // B = [S]
if (count > 0) {
this.loadBviaS(); // B = [S]
} else {
this.BROF = 0;
}
}
if (aBit < 42) {
aBit += 6;
@@ -654,7 +658,11 @@ B5500Processor.prototype.compareSourceWithDest = function(count) {
aBit = 0;
this.G = 0;
this.M++;
this.loadAviaM(); // A = [M]
if (count > 0) {
this.loadAviaM(); // A = [M]
} else {
this.AROF = 0;
}
}
}
}
@@ -855,16 +863,77 @@ B5500Processor.prototype.streamBitsToDest = function(count, mask) {
}
};
/**************************************/
B5500Processor.prototype.streamProgramToDest = function(count) {
/* Implements the TRP (Transfer Program Characters) character-mode syllable */
var bBit; // B register bit nr
var bw; // current B register value
var c; // current character
var pBit; // P register bit nr
var pw; // current P register value
this.streamAdjustDestChar();
if (count) { // count > 0
if (!this.BROF) {
this.loadBviaS(); // B = [S]
}
if (!this.PROF) {
this.loadPviaC(); // fetch the program word, if necessary
}
this.cycleCount += count; // approximate the timing
pBit = (this.L*2 + (count % 2))*6; // P-reg bit number
pw = this.P;
bBit = this.K*6; // B-reg bit number
bw = this.B;
do {
c = this.cc.fieldIsolate(pw, pBit, 6);
bw = this.cc.fieldInsert(bw, bBit, 6, c)
count--;
if (bBit < 42) {
bBit += 6;
this.K++;
} else {
bBit = 0;
this.K = 0;
this.B = bw;
this.storeBviaS(); // [S] = B
this.S++;
if (count > 0 && count < 8) { // only need to load B if a partial word is left
this.loadBviaS(); // B = [S]
bw = this.B;
} else {
this.BROF = 0;
}
}
if (pBit < 42) {
pBit += 6;
if (!(count % 2)) {
this.L++;
}
} else {
pBit = 0;
this.L = 0;
this.C++;
this.loadPviaC(); // P = [C]
pw = this.P;
}
} while (count);
this.B = bw;
this.Y = c; // for display purposes only
}
};
/**************************************/
B5500Processor.prototype.streamSourceToDest = function(count, transform) {
/* General driver for character-mode character transfers from source to
destination, such as TRS or TRZ.
"count" is the number of source characters to transfer.
"transform" is a function(bBit, count) that determines how the characters
are transferred from the source (A) to destination (B). The Y register will
contain the current char during this call */
"transform" is a function(bBit, c, count) that determines how the characters
are transferred from the source (A) to destination (B) */
var aBit; // A register bit nr
var aw; // current A register word
var bBit; // B register bit nr
var c; // current character
this.streamAdjustSourceChar();
this.streamAdjustDestChar();
@@ -877,10 +946,11 @@ B5500Processor.prototype.streamSourceToDest = function(count, transform) {
}
this.cycleCount += count*2; // approximate the timing
aBit = this.G*6; // A-bit number
aw = this.A;
bBit = this.K*6; // B-bit number
do {
this.Y = this.cc.fieldIsolate(this.A, aBit, 6);
transform.call(this, bBit, count)
c = this.cc.fieldIsolate(aw, aBit, 6);
transform.call(this, bBit, c, count)
count--;
if (bBit < 42) {
bBit += 6;
@@ -890,8 +960,10 @@ B5500Processor.prototype.streamSourceToDest = function(count, transform) {
this.K = 0;
this.storeBviaS(); // [S] = B
this.S++;
if (count < 8) { // only need to load B if a partial word is left
if (count > 0 && count < 8) { // only need to load B if a partial word is left
this.loadBviaS(); // B = [S]
} else {
this.BROF = 0;
}
}
if (aBit < 42) {
@@ -901,9 +973,15 @@ B5500Processor.prototype.streamSourceToDest = function(count, transform) {
aBit = 0;
this.G = 0;
this.M++;
this.loadAviaM(); // A = [M]
if (count > 0) { // only need to load A if there's more to do
this.loadAviaM(); // A = [M]
aw = this.A;
} else {
this.AROF = 0;
}
}
} while (count)
} while (count);
this.Y = c; // for display purposes only
}
};
@@ -937,12 +1015,14 @@ B5500Processor.prototype.streamToDest = function(count, transform) {
this.K = 0;
this.storeBviaS(); // [S] = B
this.S++;
if (count < 8) { // only need to reload B if a partial word is left
if (count > 0 && count < 8) { // only need to load B if a partial word is left
this.loadBviaS(); // B = [S]
} else {
this.BROF = 0;
}
}
}
} while (count)
} while (count);
}
};
@@ -2779,7 +2859,9 @@ B5500Processor.prototype.run = function() {
noSECL = 0; // force off by default (set by CRF)
switch (opcode & 0x3F) {
case 0x00: // XX00: CMX, EXC: Exit character mode
this.adjustBEmpty(); // store destination string
if (this.BROF) {
this.storeBviaS(); // store destination string
}
this.S = this.F;
this.loadBviaS(); // B = [S], fetch the RCW
this.exitSubroutine(variant & 0x01);// exit vs. exit inline
@@ -3404,51 +3486,12 @@ B5500Processor.prototype.run = function() {
break;
case 0x3C: // XX74: TRP=Transfer program characters
this.streamAdjustDestChar();
if (variant) { // count > 0
if (!this.BROF) {
this.loadBviaS(); // B = [S]
}
this.cycleCount += variant; // approximate the timing
t1 = (this.L*2 + (variant & 0x01))*6; // P-reg bit number
t2 = this.K*6; // B-reg bit number
do {
if (!this.PROF) {
this.loadPviaC(); // fetch the program word, if necessary
}
this.Y = this.cc.fieldIsolate(this.P, t1, 6);
this.B = this.cc.fieldInsert(this.B, t2, 6, this.Y)
if (t2 < 42) {
t2 += 6;
this.K++;
} else {
t2 = 0;
this.K = 0;
this.storeBviaS(); // [S] = B
this.S++;
if (variant < 8) { // just a partial word left
this.loadBviaS(); // B = [S]
}
}
if (t1 < 42) {
t1 += 6;
if (!(variant & 0x01)) {
this.L++;
}
} else {
t1 = 0;
this.L = 0;
this.C++;
this.loadPviaC(); // P = [C]
}
} while (--variant);
}
this.streamProgramToDest(variant);
break;
case 0x3D: // XX75: TRN=Transfer source numerics
this.MSFF = 0; // initialize true-false FF
this.streamSourceToDest(variant, function(bb, count) {
var c = this.Y;
this.streamSourceToDest(variant, function(bb, c, count) {
if (count == 1 && (c & 0x30) == 0x20) {
this.MSFF = 1; // neg. sign
@@ -3458,14 +3501,14 @@ B5500Processor.prototype.run = function() {
break;
case 0x3E: // XX76: TRZ=Transfer source zones
this.streamSourceToDest(variant, function(bb, count) {
this.B = this.cc.fieldInsert(this.B, bb, 2, this.Y >>> 4);
this.streamSourceToDest(variant, function(bb, c, count) {
this.B = this.cc.fieldInsert(this.B, bb, 2, c >>> 4);
});
break;
case 0x3F: // XX77: TRS=Transfer source characters
this.streamSourceToDest(variant, function(bb, count) {
this.B = this.cc.fieldInsert(this.B, bb, 6, this.Y);
this.streamSourceToDest(variant, function(bb, c, count) {
this.B = this.cc.fieldInsert(this.B, bb, 6, c);
});
break;

View File

@@ -34,8 +34,8 @@ var B5500SystemConfiguration = {
false, // Memory module 3 available (4KW)
true, // Memory module 4 available (4KW)
true, // Memory module 5 available (4KW)
false, // Memory module 6 available (4KW)
false], // Memory module 7 available (4KW)
true, // Memory module 6 available (4KW)
true], // Memory module 7 available (4KW)
units: {
SPO: true, // SPO keyboard/printer

BIN
tests/KERNEL.DISK Normal file

Binary file not shown.

View File

@@ -1686,7 +1686,7 @@ window.onload = function() {
pow2[47-28] + // 28: prevent I/O below user disk area
pow2[47-27] + // 27: prevent disk RELEASE statement
pow2[47-26] + // 26: printer backup disk release
pow2[47-25] + // 25: check memory links
// 25: check memory links
pow2[47-24] + // 24: type disk error messages
pow2[47-23] + // 23: disk logging
pow2[47-22] + // 22: suppress library error messages
@@ -1713,7 +1713,7 @@ window.onload = function() {
// 1: UNUSED
0; // 0: (flag bit)
info[ 1] = 0x1001200; // Date: BIC "00010180" = 1980-01-01
info[ 1] = 0x8000001; // Date: BIC "00080001" = 80001 = 1980-01-01
info[ 2] = config.eus; // number of EUs
info[ 3] = 0; // not used
info[ 4] = directoryEnd; // DIRECT deck option
@@ -1721,7 +1721,7 @@ window.onload = function() {
info[ 6] = 0; // first control deck queued
info[ 7] = 0; // last control deck queued
info[ 8] = 0; // next number available for printer backup disk
info[ 9] = 1; // multiprocessing core factor
info[ 9] = 100; // multiprocessing core factor
info[10] = 0; // SPO stations (through info[15])
info[11] = 0;
info[12] = 0;

View File

@@ -110,6 +110,18 @@ TD#TMnemonic {
text-align: center;
background-color: #EEF;
font-size: smaller}
TD.notReady {
visibility: hidden}
TD.ready {
visibility: visible;
text-align: center;
font-weight: bold;
color: green}
TD.busy {
visibility: visible;
text-align: center;
font-weight: bold;
color: red}
INPUT.warn {
background-color: yellow}

View File

@@ -375,10 +375,11 @@ function decodeSyllable(syllable, mode, level, msff) {
}
break;
case 9:
text += wordOps[opcode];
text += wordOps[opcode] || "????";
break;
default:
text += charOps[padOctal(syllable % 64, 4)] + " " + padOctal(v, 2) + " (" + v + ")";
text += (charOps[padOctal(syllable % 64, 4)] || "????") + " " +
padOctal(v, 2) + " (" + v + ")";
break;
} // switch on lower half of char-mode syllable
@@ -461,7 +462,11 @@ function displayNumber(id, value) {
var t = (e & 0x40) >>> 6; // get the exponent sign
e = (t ? -(e & 0x3F) : (e & 0x3F)); // get signed value of exponent
setText(id, (Math.pow(8, e)*(s ? -m : m)).toPrecision(12));
if (e) {
setText(id, (Math.pow(8, e)*(s ? -m : m)).toPrecision(12));
} else {
setText(id, m.toString());
}
}
function displayBIC(id, value) {
@@ -605,13 +610,38 @@ function displayRegisters() {
$$("VARF").checked = (cc.P1.VARF != 0);
}
function displayProcessorState() {
function displayCentralControl() {
/* Displays the I/O and interrupt status in Central Control */
var cells;
var s;
var ubm = cc.unitBusyMask;
var usm = cc.unitStatusMask;
var x;
$$("AD1F").className = (cc.AD1F ? "busy" : "notReady");
$$("AD2F").className = (cc.AD2F ? "busy" : "notReady");
$$("AD3F").className = (cc.AD3F ? "busy" : "notReady");
$$("AD4F").className = (cc.AD4F ? "busy" : "notReady");
for (x=3; x<=16; x++) {
s = "CCI" + (x+100).toString().substring(1) + "F";
$$(s).className = (cc[s] ? "busy" : "notReady");
}
cells = $$("CCPeripheralRow").cells;
for (x=17; x<=47; x++) {
cells[x-16].className = (cc.bit(usm, x) ? (cc.bit(ubm, x) ? "busy" : "ready") : "notReady");
}
}
function displaySystemState() {
/* Extracts and displays the current processor state on the web page */
displayStack();
displayMemory();
displayRegisters();
window.focus();
displayCentralControl();
//window.focus();
}
function goIt(ev) {
@@ -628,7 +658,7 @@ function goIt(ev) {
cc.P1.L = 0;
cc.P1.C++;
}
displayProcessorState();
displaySystemState();
}
function stepIt(ev) {
@@ -637,6 +667,7 @@ function stepIt(ev) {
be executed next */
var next;
ev.target.disabled = true;
setText("ARegOrig", padOctal(cc.P1.A, 16));
setText("BRegOrig", padOctal(cc.P1.B, 16));
@@ -647,35 +678,47 @@ function stepIt(ev) {
cc.P1.C = (next - cc.P1.L)/4;
}
cc.P1.step();
displayProcessorState();
displaySystemState();
ev.target.disabled = false;
}
function runIt(ev) {
/* Steps through instructions continuously until the C register matches the
StopAddr address. StopAddr can be changed while running. Setting it to zero
(or blank) will halt the continuous stepping */
var runBtn = $$("RunBtn");
var saveStopAddress = stopAddress;
var stopAddr = $$("StopAddr");
function syllabicate() {
if (stopAddress && cc.P1.C != stopAddress) {
cc.P1.step();
displayProcessorState();
displaySystemState();
if (isNaN(stopAddress)) {
stopAddress = 0; // bad address
stopAddr.style.backgroundColor = "red";
stopAddress = 0; // bad address -- kill the loop
runBtn.value = "Run";
} else {
setTimeout(syllabicate, 1);
setTimeout(syllabicate, 0);
}
} else {
stopAddress = saveStopAddress;
stopAddr.style.backgroundColor = "";
stopAddr.value = padOctal(stopAddress, stopAddr.maxLength);
runBtn.value = "Run";
}
}
setText("ARegOrig", "");
setText("BRegOrig", "");
injected = false;
stopAddr.style.backgroundColor = "green";
syllabicate();
if (runBtn.value != "Run") {
stopAddress = 0; // stop syllabicating
} else {
setText("ARegOrig", "");
setText("BRegOrig", "");
injected = false;
stopAddr.style.backgroundColor = "green";
runBtn.value = "Stop";
syllabicate();
}
}
function word_onChange(ev) {
@@ -763,7 +806,7 @@ function fileLoader_onLoad(ev) {
}
if (words > 0) {
cc.P1.preset(0x10); // execute from address @20
displayProcessorState();
displaySystemState();
}
}
@@ -802,7 +845,7 @@ function initialize() {
}, false);
$$("LogoDiv").onclick = function(ev) {
displayProcessorState();
displaySystemState();
};
$$("AReg").onchange = function(ev) {
@@ -969,7 +1012,7 @@ function initialize() {
cc.P1.NCSF = 0; // initiate test in control state
displayProcessorState();
displaySystemState();
displayOctal("StopAddr", stopAddress, 5);
}
@@ -1283,7 +1326,68 @@ window.onload = function() {
Stop at
<input id=StopAddr name=StopAddr type=text class=number size=5 maxlength=5>
&nbsp;
<input id=RunBtn name=RunBtn type=button value="Run" accesskey=X>
<input id=RunBtn name=RunBtn type=button value="Run" accesskey=R>
</table>
<table id=CentralControl>
<colgroup>
<col span=32 style="width:3%">
</colgroup>
<thead>
<tr id=CCInterruptRow>
<td>CC:
<td id=AD1F>IOU1 <!-- I/O unit 1 busy -->
<td id=AD2F>IOU2 <!-- I/O unit 2 busy -->
<td id=AD3F>IOU3 <!-- I/O unit 3 busy -->
<td id=AD4F>IOU4 <!-- I/O unit 4 busy -->
<td id=CCI03F>TIMR <!-- Time interval interrupt -->
<td id=CCI04F>IOBZ <!-- I/O busy interrupt -->
<td id=CCI05F>KBD <!-- Keyboard request interrupt -->
<td id=CCI06F>PR1F <!-- Printer 1 finished interrupt -->
<td id=CCI07F>PR2F <!-- Printer 2 finished interrupt -->
<td id=CCI08F>IO1F <!-- I/O unit 1 finished interrupt (RD in @14) -->
<td id=CCI09F>IO2F <!-- I/O unit 2 finished interrupt (RD in @15) -->
<td id=CCI10F>IO3F <!-- I/O unit 3 finished interrupt (RD in @16) -->
<td id=CCI11F>IO4F <!-- I/O unit 4 finished interrupt (RD in @17) -->
<td id=CCI12F>P2BZ <!-- P2 busy interrupt -->
<td id=CCI13F>INQ <!-- Remote inquiry request interrupt -->
<td id=CCI14F>SPEC <!-- Special interrupt #1 (not used) -->
<td id=CCI15F>DK1F <!-- Disk file #1 read check finished -->
<td id=CCI16F>DK2F <!-- Disk file #2 read check finished -->
<td colspan=13>
<tr id=CCPeripheralRow>
<td>PER:
<td id=DCA>DCA <!-- 17 -->
<td id=PPB>PPB <!-- 18 -->
<td id=PRB>PRB <!-- 19 -->
<td id=PRA>PRA <!-- 20 -->
<td id=PPA>PPA <!-- 21 -->
<td id=SPO>SPO <!-- 22 -->
<td id=CRB>CRB <!-- 23 -->
<td id=CRA>CRA <!-- 24 -->
<td id=CPA>CPA <!-- 25 -->
<td id=LPB>LPB <!-- 26 -->
<td id=LPA>LPA <!-- 27 -->
<td id=DKB>DKB <!-- 28 -->
<td id=DKA>DKA <!-- 29 -->
<td id=DRB>DRB <!-- 30 -->
<td id=DRA>DRA <!-- 31 -->
<td id=MTT>MTT <!-- 32 -->
<td id=MTS>MTS <!-- 33 -->
<td id=MTR>MTR <!-- 34 -->
<td id=MTP>MTP <!-- 35 -->
<td id=MTN>MTN <!-- 36 -->
<td id=MTM>MTM <!-- 37 -->
<td id=MTL>MTL <!-- 38 -->
<td id=MTK>MTK <!-- 39 -->
<td id=MTJ>MTJ <!-- 40 -->
<td id=MTH>MTH <!-- 41 -->
<td id=MTF>MTF <!-- 42 -->
<td id=MTE>MTE <!-- 43 -->
<td id=MTD>MTD <!-- 44 -->
<td id=MTC>MTC <!-- 45 -->
<td id=MTB>MTB <!-- 46 -->
<td id=MTA>MTA <!-- 47 -->
</table>
</body>