1
0
mirror of https://github.com/pkimpel/retro-b5500.git synced 2026-02-12 03:07:30 +00:00

Commit DCMCP transcription as of 2012-06-03; commit initial emulator

module constructors.
This commit is contained in:
paul
2012-06-04 02:26:26 +00:00
parent 0d1fc70032
commit 0c339bc280
4 changed files with 722 additions and 1 deletions

View File

@@ -2338,3 +2338,236 @@ ARRAY MAINTBUFFER[*]; 04121950
END 04134950
ELSE GO TO DC; 04134955
END ELSE GO TO X; 04134960
END; 04134990
IF E = 0 THEN 04135000
BEGIN % RECOVERED MASS STORAGE % 04137000
MAINTBUFFER[NXDISK:=NXDISK+4 AND 15] 04137100
:= -0 & U[2:46:2] & LOCATQUE[S][4:3:5] & 04137110
(LOIGENTRY:=LOGENTRY+1)[CTF] & 04137120
RDCTABLE[U]{18:1:2]; 04137130
IF FINALQUE[S] GTR 0 THEN 04137140
BEGIN 04137150
MAINTBUFFER[XNDISK]:=(*P(DUP)) & 04137160
((M[M[S1:=LOCATQUE[S] INX NOT 2] INX 4]04137170
.[13:11] DIV ETRLNG)+1)[9:39:9]; 04137180
M[S1].[7:1] := 1; 04137190
END; 04137200
P(MAINTBUFFER[NXDISK+2]:=IOQUE[S]); 04137202
$ SET OMIT = NOT(AUXMEM) 04137203
P(NFLAG(M[P])); 04137212
P(P&V[1:44:4],[MAINTBUFFER[NXDISK+1]],STD); 04137215
MAINTBUFFER[NXDISK+3]:=MAINTBUFFER[U]; 04137220
IF (LOGHOLDER INX 0) = 0 THEN 04137230
BEGIN 04137240
LOGHOLDER.[CF]:=[MAINTBUFFER[NXDISK]]; 04137250
INDEPENDENTRUNNER(P(.MAINTLOGGER),0,100); 04137260
END ELSE M[LOGHOLDER.[FF]].[CF]:= 04137270
[MAINTBUFFER[NXDISK]]; 04137275
LOGHOLDER.[FF]:=[MAINTBUFFER[NXDISK]]; 04137280
NUMAINTMESS:= NUMAINTMESS+1; 04137290
T.[5:8] ~ 0; 04142000
GO TO SW; 04142500
END;% 04143000
IF V = 0 THEN% 04144000
$ SET OMIT = NOT(SHAREDISK) 04144099
BEGIN % ORIGINAL ERROR ON MASS STORAGE% 04145000
TINU[U].[18:2] ~ P(DUP).[18:12]+1;% 04146000
MAINTBUFFER[U]:=R&TWO(C)[18:43:4]; 04146100
RDCTABLE[U]:=(*P(DUP))&(C-1)[1:46:2]; 04146200
V:=129; 04147000
$ SET OMIT = NOT(SHAREDISK) 04147399
END% 04148000
ELSE BEGIN % RECURRENT ERROR ON MASS STORAGE% 04149000
P(MAINTBUFFER[U]:=P(DUP,LOD) OR 04150100
R&TWO(C)[18:43:4]); 04150200
IF (V ~ V+1) > 137 THEN% 04151000
BEGIN R:=P; 04151200
IF LOCATQUE[S].[9:1] THEN % OLAY I/O 04151220
M[LOCATQUE[S]:=R OR IOMASK; 04151230
$ SET OMIT = NOT(AUXMEM) 04151235
DISKERR: 04151300
$ SET OMIT = NOT(DFX) 04151399
T.[5:10]:=0; 04151400
GO TO DX; 04152600
END; 04152800
P(DEL); 04152900
END;% 04153000
UNIT[U] ~ T&V[5:40:8];% 04154000
DS:% 04155000
CHANNEL[P(TIO)] ~ U;% 04156000
P([IOQUE[S]],IIO);% 04157000
GO TO EXTERNAL ;% 04158000
X: STOP ~ (V!0)|2+1;% 04159000
T.[5:13] ~ 32|E+8;% 04160000
GO TO TEST; 04161000
END; 04161500
SW:: GO TO TYPE[T.[1:4]];% 04162000
LP: 04163000
IF STOP := (T := T&0[16:16:1]).[17:1] THEN 04164000
TEST: IF FIRSTWAIT = NEXTWAIT THEN GO TO INCR ELSE% 04165000
GO TO NEW ELSE GO TO NOWAIT;% 04166000
DK: 04167900
IF NOT (I:=IOQUE[S]).[24:1] THEN 04168000
IF FINALQUE[S].[24:1] THEN% 04169000
$ SET OMIT = DFX 04169090
BEGIN 04169100
$ SET OMIT = NOT DKBNODFX OR OMIT 04169190
$ SET OMIT = DKBNODFX OR OMIT 04170750
M[IOQUE[S]:=I&1[24:47:1]]:=*(P(DUP) INX P(0,LNG,XCH)); 04170800
$ POP OMIT 04170900
GO TO DS; 04171000
END ELSE GO TO OK ELSE GO TO OK; 04171200
$ POP OMIT 04171250
$ SET OMIT = NOT DFX 04171350
DC: 04174000
$ SET OMIT = NOT(DATACOM ) 04174999
04176000
$ SET OMIT = DFX 04176899
DX: DX1: 04176900
$ POP OMIT 04176901
OK: IF FIRSTWAIT = NEXTWAIT THEN 04177000
NOWAIT: IF (S1 := LOCATQUE[S].[18:15]) LSS @1777 THEN 04178000
INITIATEIO(IOQUE[S1],LOCATQUE[S1].[3:5],U)% 04180000
ELSE 04181000
PROC: T := T&0[16:16:2] 04182000
ELSE 04183000
BEGIN% 04187000
NEW: NEWIO;% 04188000
IF STOP THEN GO TO INCR;% 04189000
QUP: IF LOCATQUE[S].[FF] GTR @1777 THEN GO TO PROC; 04190000
QUEUEUP(U);% 04191000
T ~ T&4[13:43:5];% 04192000
END;% 04193000
INCR: 04194000
IF (TIM~CLOCK+P(RTR)-TIM) LSS THEN THEN TIM~0; 04194050
IOD:=IOQUE[S]; 04194100
IF (U OR 1 )=19 THEN 04194200
BEGIN 04194300
IF (JUNK:=M[IOD].[5:7])>9 THEN 04194400
JUNK:=NEUP.[CF]+(JUNK AND @17); 04194500
IF JUNK<NEUP.[FF] THEN 04194550
PEUIO[JUNK]:=P(DUP,LOD)+CLOCK+P(RTR)-EUIO[C]; 04194600
END; 04194650
I~(S1~LOCATQUE[S]).[3:5]; % FIND MIX INDEX 04194700
$ SET OMIT = NOT(NEWLOGGING) 04194799
IOTIME[I]~(*P(DUP))+TIM; 04195000
IF P(.S1,LOD).[10:1] THEN FORGETSPACE(IOD); % NO MEM MESSAGE 04195100
IF F!0 THEN 04196200
IF STOP THEN 04196400
P(T) 04196600
ELSE GO TO L1 04196800
ELSE BEGIN 04197000
RETURNIOSPACE(S); 04199000
L1: P(T&P(.L1,LOD)[FTF]); 04201000
END; 04202000
P([UNIT[U]],STD); 04203000
FIN ~ FINALQUE[S] AND NOT MEMORY;% 04205000
IF (U OR 1) NEQ 17 THEN 04205012
IF IOD.[24:1] THEN% 04206000
BEGIN V ~ ABS(IOD.[33:15]-R.[33:15]);% 04207000
IF IOD.[8:10] < V THEN% 04208000
IF IOD.[23:1] THEN% 04209000
V ~ IOD.[8:10];% 04210000
IF U < 16 THEN% 04211000
IF IOD.[21:2] = 0 THEN% 04212000
BEGIN; STREAM(A!0:B~M[S1.[33:15]+V-1]);% 04213000
BEGIN SI ~ LOC B;% 04214000
IF SC = "~" THEN TALLY ~ 1;% 04215000
A ~ TALLTY;% 04216000
END;% 04217000
V ~ -P+V;% 04218000
END;% 04219000
IF U ! 30 THEN % NOT DCA 04219100
FINISHOFFIO(U);% 04220000
END;% 04221000
IF E ! 0 THEN% 04222000
$ SET OMIT = NOT(SHAREDISK) 04222499
BEGIN IF STOP LEQ 1 THEN 04223000
BEGIN 04223500
INDEPENDENTRUNNER( 04224000
P(.DISKORAUXERROR)+((U AND @774) NEQ 16), 04224010
R&S[3:43:5],240); 04224100
LOCATQUE[S].[11:1]:=1; 04224500
END 04224750
ELSE IF FIN < 0 THEN P(LOCATQUE[S],R,XCH,~);% 04225000
END% 04226000
$ SET OMIT = NOT(SHAREDISK) 04226499
ELSE BEGIN% 04227000
IF FIN < 0 THEN P(R OR IOMASK,LOCATQUE[S],~)% 04228000
ELSE 04229000
$ SET OMIT = NOT (DATACOM OR DFX OR DKBNODFX) 04229099
BEGIN 04229200
LOCN ~ [M[LOCATQUE[S]]];% 04230000
IOD ~ IOD.[33:15];% 04231000
WHILE LOCN[0].[33:15] ! IOD DO% 04232000
LOCN ~ 1 INX LOCN;% 04233000
LOCN[0] ~ M OR FIN;% 04234000
END END;% 04235000
IF P1MIX = 0 THEN GO TO NOTHINGTODO;% 04236000
IF I = P1MIX THEN GO TO RETURN;% 04237000
GO TO INITIATE;% 04238000
END IOCOMPLETE;% 04239000
SAVE REAL PROCEDURE WAITIO(IOD,MASK,U);% 04240000
VALUE MASK,U,IOD;% 04241000
REAL MASK,U,IOD;% 04242000
BEGIN% 04243000
REAL T; 04243100
DEFINE OCTADE= DS~3 RESET;3(IF SB THEN DS!SET ELSE 04243200
DS~RESET;SKIP SB)#; 04243300
IOD ~ NFLAG(P(.IOD,LOC))&TINU[U][3:3:5];% 04244000
MASK ~ NOT MASK;% 04245000
IOREQUEST(NABS(IOD)&MASK[25:40:8],IOD, 04246000
[IOD]&U[12:42:6]);% 04247000
IOD ~ IOD&0[25:25:8]&0[19:19:1];% 04248000
SLEEP([IOD],IOMASK);% 04249000
IF ((WAITIO~IOD.[26:7]) AND MASK AND MAKS.[18:15])!0 THEN 04250000
BEGIN 04251000
T~SPACE(12); 04251100
STREAM(IOD~IOD.[26:7],MASK~(NOT MASK).[41:7], 04251200
Z~[TINU[U]],T~T); 04251300
BEGIN DS~20 LIT" UNEXP I-O ERROR ON ";SI~Z; 04251400
SI~SI+5;DS~3 CHR;DS~8 LIT":RESULT="; 04251500
SI~LOC IOD;SI~SI+6;SKIP 3 SB;3(OCTADE); 04251600
DS~6 LIT",MASK=" ;SI~SI+6;SKIP 3 SB; 04251700
3(OCTADE);DS~2 LIT".~"; 04251800
END; 04251900
IF P1MIX = 0 THEN BEGIN P(T); PUNT(0) END; 04252000
IF NOTERMSET(P1MIX) THEN 04252100
BEGIN 04252200
TERMINATE(P1MIX&19[18:33:15]); 04252300
IF JAR[P1MIX,9].SYSJOBF THEN %SYSTEM JOB 04252500
BEGIN 04252600
SPOUT(T); 04252700
BLASTQ(U); 04252800
END ELSE 04252900
TERMINALMESSAGE(-T); 04253000
END; 04253100
END; 04253200
END; 04253300
REAL PROCEDURE TAPEPARITYRETRY(R,U,KEY);% 04254000
VALUE R,U,KEY; REAL R,U,KEY; FORWARD; 04255000
REAL PROCEDURE WRITEPARITYREELSWITCH(OIOD,RC); 04255100
VALUE OIOD,REC; REAL OIOD,RC; FORWARD; 04255200
PROCEDURE DISKORAUXERROR(R); VALUE R; REAL R; 04256000
04256200
BEGIN 04256400
REAL MSCW = -2, 04256600
U = +1, 04256800
S = +2, 04257000
E = +3, 04257200
T = +4, 04257400
MK = +5, CELL = MK, 04257600
IOD = +6, 04257800
MIX = +7, 04258000
FIN = +8, PARITY= FIN, 04258200
KEY1 = +9, 04258400
KEY2 = +10, 04258600
DISC = +11, 04258800
MASK = +12, 04259000
AREA = +13, U1 = AREA, 04259200
RLST = +14, MSG = RSLT, 04259400
PRTMAX = +15, T1 = PRTMAX, 04259600
DISKCELL= +16, T2 = DISKCELL, 04259800
TERMNATE = +17, 04260000
OLAYIO = +18, 04260200
DSKADRS = +19; 04260400

View File

@@ -0,0 +1,114 @@
/***********************************************************************
* retro-b5500/emulator B5500CentralControl.js
************************************************************************
* Copyright (c) 2012, Nigel Williams and Paul Kimpel.
* Licensed under the MIT License, see http://www.opensource.org/licenses/mit-license.php
************************************************************************
* JavaScript object definition for the B5500 Central Control module.
************************************************************************
* 2012-06-03 P.Kimpel
* Original version, from thin air.
***********************************************************************/
/**************************************/
function B5500CentralControl() {
/* Constructor for the Central Control module object */
this.IAR = 0; // Interrupt address register
this.TM = 0; // Real-time clock (6 bits, 60 ticks per second)
this.CCI03F = 0; // Time interval interrupt
this.CCI04F = 0; // I/O busy interrupt
this.CCI05F = 0; // Keyboard request interrupt
this.CCI06F = 0; // Printer 1 finished interrupt
this.CCI07F = 0; // Printer 2 finished interrupt
this.CCI08F = 0; // I/O unit 1 finished interrupt (RD in @14)
this.CCI09F = 0; // I/O unit 2 finished interrupt (RD in @15)
this.CCI10F = 0; // I/O unit 3 finished interrupt (RD in @16)
this.CCI11F = 0; // I/O unit 4 finished interrupt (RD in @17)
this.CCI12F = 0; // P2 busy interrupt
this.CCI13F = 0; // Remote inquiry request interrupt
this.CCI14F = 0; // Special interrupt #1 (not used)
this.CCI15F = 0; // Disk file #1 read check finished
this.CCI16F = 0; // Disk file #2 read check finished
this.AD1F = 0; // I/O unit 1 busy
this.AD2F = 0; // I/O unit 2 busy
this.AD3F = 0; // I/O unit 3 busy
this.AD4F = 0; // I/O unit 4 busy
this.LOFF = 0; // Load button pressed on console
this.CTMF = 0; // Commence timing FF
this.P2BF = 0; // Processor 2 busy FF
this.HP2F = 0; // Halt processor 2 FF
this.PB1L = 0; // 0=> PA is P1, 1=> PB is P1
this.rtcTick = 1000/60; // Real-time clock period, milliseconds
this.nextTimeStamp = 0; // Next actual Date.getTime() expected
}
/**************************************/
B5500CentralControl.prototype.fetch(addr) {
/* Called by all modules to fetch a word from memory. /*
// TO BE PROVIDED
}
/**************************************/
B5500CentralControl.prototype.store(addr, word) {
/* Called by all modules to fetch a word from memory. /*
// TO BE PROVIDED
}
/**************************************/
B5500CentralControl.prototype.signalInterrupt() {
/* Called by all modules to signal that an interrupt has occurred and
to invoke the interrupt prioritization mechanism. This will result in
an updated vector address in the IAR. /*
// TO BE PROVIDED
}
/**************************************/
B5500CentralControl.prototype.clear() {
/* Initializes the system and starts the real-time clock */
this.nextTimeStamp = new Date().getTime() + this.rtcTick;
setTimeout(this.tock, this.rtcTick);
}
/**************************************/
B5500CentralControl.prototype.tock() {
/* Handles the 1/60th second real-time clock increment */
var thisTime = new Date().getTime();
if (this.TM < 63) {
this.TM++;
} else {
this.TM = 0;
this.CCI03F = 1; // set timer interrupt
this.signalInterrupt();
}
this.nextTimeStamp += this.rtcTick;
if (this.nextTimeStamp < thisTime) {
setTimeout(this.tock, 1); // try to catch up
} else {
setTimeout(this.tock, this.nextTimeStamp-thisTime);
}
}
/**************************************/
B5500CentralControl.prototype.halt() {
/* Halts the system */
// TO BE PROVIDED
}
/**************************************/
B5500CentralControl.prototype.load() {
/* Initiates a Load operation to start the system */
// TO BE PROVIDED
}

374
emulator/B5500Processor.js Normal file
View File

@@ -0,0 +1,374 @@
/***********************************************************************
* 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
************************************************************************
* JavaScript object definition for the B5500 Processor (CPU) module.
************************************************************************
* 2012-06-03 P.Kimpel
* Original version, from thin air.
***********************************************************************/
/**************************************/
function B5500Processor() {
/* Constructor for the Processor module object */
this.A = 0; // Top-of-stack register 1
this.AROF = 0; // A contents valid
this.B = 0; // Top-of-stack register 2
this.BROF = 0; // B contents valid
this.C = 0; // Current program instruction word address
this.CCCF = 0; // Clock-count control FF (maintenance only)
this.CWMF = 0; // Character/word mode FF (1=CM)
this.E = 0; // Memory access control register
this.EIHF = 0; // ??
this.F = 0; // Top MSCW/RCW stack address
this.G = 0; // Character index register for A
this.H = 0; // Bit index register for G (in A)
this.HLTF = 0; // Processor halt FF
this.I = 0; // Processor interrupt register
this.K = 0; // Character index register for B
this.L = 0; // Instruction syllable index in P
this.M = 0; // Memory address register (SI.w in CM)
this.MRAF = 0; // Memory read access FF
this.MROF = 0; // Memory read obtained FF
this.MSFF = 0; // Mark-stack FF (word mode: MSCW is pending RCW, physically also TFFF & Q12F)
this.MWOF = 0; // Memory write obtained FF
this.N = 0; // Octal shift counter for B
this.NCSF = 0; // Normal/control state FF (1=normal)
this.P = 0; // Current program instruction word register
this.PROF = 0; // P contents valid
this.Q = 0; // Misc. FFs (bits 1-9 only: Q07F=hardware-induced interrupt, Q09F=enable parallel adder for R-relative addressing)
this.R = 0; // PRT base address (high-order 9 bits only)
this.S = 0; // Top-of-stack memory address (DI.w in CM)
this.SALF = 0; // Program/subroutine state FF (1=subroutine)
this.T = 0; // Current program syllable register
this.TALLY = 0; // CM TALLY register (physically, low-order 6 bits of R)
this.TM = 0; // Temporary maintenance storage register
this.TROF = 0; // T contents valid
this.V = 0; // Bit index register for K (in B)
this.VARF = 0; // Variant-mode FF (enables full PRT indexing)
this.X = 0; // Mantissa extension for B (loop control in CM)
this.Y = 0; // Serial character register for A
this.Z = 0; // Serial character register for B
this.cycleLimit = 0; // Count-down cycle limit for this.run()
this.isP1 = true; // Control processor flag
}
/**************************************/
B5500Processor.prototype.access(eValue) {
/* Access memory based on the E register */
var addr;
/****************************************************************
HOW TO HANDLE INVALID ADDRESS INTERRUPTS DETECTED BY CENTRAL CONTROL?
****************************************************************/
this.E = eValue;
switch (eValue) {
case 0x02: // A = [S]
this.A = cc.fetch(this.S);
this.AROF = 1;
break;
case 0x03: // B = [S]
this.B = cc.fetch(this.S);
this.BROF = 1;
break;
case 0x04: // A = [M]
this.A = cc.fetch(this.M);
this.AROF = 1;
break;
case 0x05: // B = [M]
this.B = cc.fetch(this.M);
this.BROF = 1;
break;
case 0x06: // M = [M].[18:15]
this.M = (cc.fetch(this.M) >>> 15) & 0x7FFF;
break;
case 0x0A: // [S] = A
cc.store(this.S, this.A);
break;
case 0x0B: // [S] = B
cc.store(this.S, this.B);
break;
case 0x0C: // [M] = A
cc.store(this.M, this.A);
break;
case 0x0D: // [M] = B
cc.store(this.M, this.B);
case 0x30: // P = [C]
this.P = cc.fetch(this.C);
this.PROF = 1;
break;
default:
throw "Invalid E register value: " + eReg.toString(2);
break;
}
this.cycleLimit -= 6; // assume 6 us memory cycle time
if (addr < 0x0200 && this.NCSF) { // normal-state cannot address @000-@777 [?? first 512 or 1024 words ??]
this.I |= 0x0500; // set I02F & I04F
cc.signalInterrupt();
} else {
cc.store(addr, word);
}
}
/**************************************/
B5500Processor.prototype.adjustAEmpty() {
/* 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.BROF) {
this.S++;
this.access(0x0B); // [S] = B
}
this.B = this.A;
this.AROF = 0;
this.BROF = 1;
// else we're done -- A is already empty
}
}
/**************************************/
B5500Processor.prototype.adjustAFull() {
/* Adjusts the A register so that it is full, popping the contents of
B or [S] into A, as necessary. */
if (!this.AROF) {
if (this.BROF) {
this.A = this.B;
this.AROF = 1;
this.BROF = 0;
} else {
this.access(0x02); // A = [S]
this.S--;
}
// else we're done -- A is already full
}
}
/**************************************/
B5500Processor.prototype.adjustBEmpty() {
/* Adjusts the B register so that it is empty pushing the prior
contents of B into memory, as necessary. */
if (this.BROF) {
this.S++;
this.access(0x0B); // [S] = B
// else we're done -- B is already empty
}
}
/**************************************/
B5500Processor.prototype.adjustBFull() {
/* Adjusts the B register so that it is full popping the contents of
[S] into B, as necessary. */
if (!this.BROF) {
this.access(0x03); // B = [S]
this.S--;
// else we're done -- B is already full
}
}
/**************************************/
B5500Processor.storeForInterrupt() {
/* Implements the 3011=SFI operator */
if (this.CWMF) {
if (this.BROF) {
this.access(0x0B); // [S] = B, save B if valid
}
if (this.AROF) {
this.access(0x0A); // [S] = A, save A if valid
}
this.B = ((((0x30*512 +
(this.R >>> 6))*4 +
this.MSFF)*2 +
this.SALF)*32768 +
this.N)*16 +
this.M;
this.S++;
this.access(0x0B);
} else
}
}
/**************************************/
B5500Processor.prototype.run() {
/* 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. */
var opcode;
/* HOW TO ENTER, EXIT, AND RESUME CHARACTER MODE? */
this.cycleLimit = 5000; // max CPU cycles to run
do {
opcode = this.T;
switch (opcode & 3) {
case 0: // LITC: Literal Call
this.adjustAEmpty();
this.A = opcode >>> 2;
this.AROF = 1;
break;
case 2: // OPDC: Operand Call
this.adjustAEmpty();
// TO BE PROVIDED
break;
case 3: // DESC: Descriptor (name) Call
this.adjustAEmpty();
// TO BE PROVIDED
break;
case 1: // all other word-mode operators
switch (opcode & 0x3F) {
case 0x01: // XX01: single-precision numerics
break;
case 0x05: // XX05: double-precision numerics
break;
case 0x09: // XX11: control state and communication ops
switch (opcode >>> 6) {
case 0x01: // 0111: PRL=Program Release
break;
case 0x10: // 1011: COM=Communicate
this.adjustAFull();
this.M = 0x09; // address @11
this.access(0x0C); // [M] = A
this.AROF = 0;
break;
case 0x02: // 0211: ITI=Interrogate Interrupt
break;
case 0x04: // 0411: RTR=Read Timer
adjustAEmpty();
this.A = cc.CCI03F << 6 | cc.TM;
break;
case 0x11: // 2111: IOR=I/O Release
break;
case 0x12: // 2211: HP2=Halt Processor 2
break;
case 0x14: // 2411: ZPI=Conditional Halt
break;
case 0x18: // 3011: SFI=Store for Interrupt
this.storeForInterrupt();
break;
case 0x1C: // 3411: SFT=Store for Test
break;
case 0x21: // 4111: IP1=Initiate Processor 1
break;
case 0x22: // 4211: IP2=Initiate Processor 2
break;
case 0x24: // 4411: IIO=Initiate I/O
break;
case 0x29: // 5111: IFT=Initiate For Test
break;
default:
break; // Anything else is a no-op
} / end switch for XX11 ops
break;
case 0x0D: // XX15: logical (bitmask) ops
break;
case 0x11: // XX21: load & store ops
break;
case 0x15: // XX25: comparison & misc. stack ops
break;
case 0x19: // XX31: branch, sign-bit, interrogate ops
break;
case 0x1D: // XX35: exit & return ops
break;
case 0x21: // XX41: index, mark stack, etc.
break;
case 0x25: // XX45: ISO=Variable Field Isolate op
break;
case 0x29: // XX51: delete & conditional branch ops
break;
case 0x2D: // XX55: NOOP & DIA=Dial A ops
if (opcode & 0xFC0) {
this.G = opcode >>> 9;
this.H = (opcode >>> 6) & 7;
// else 0055=NOOP
}
break;
case 0x31: // XX61: XRT & DIB=Dial B ops
if (opcode & 0xFC0) {
this.K = opcode >>> 9;
this.V = (opcode >>> 6) & 7;
} else { // 0061=XRT: temporarily set full PRT addressing mode
this.VARF = this.SALF;
this.SALF = 0;
}
break;
case 0x35: // XX65: TRB=Transfer Bits op
break;
case 0x39: // XX71: FCL=Compare Field Low op
break;
case 0x3D: // XX75: FCE=Compare Field Equal op
break;
default:
break; // should never get here, but in any case it'd be a no-op
} // end switch for word-mode operators
break;
} // end switch for main opcode dispatch
// SECL: Syllable Execution Complete Level
this.Q = 0;
this.Y = 0;
this.Z = 0;
if (this.CWMF) {
this.M = 0;
this.N = 0;
this.X = 0;
}
if (cc.IAR && this.NCSF) { // there's an interrupt and we're in normal state
this.T = 0x0609; // inject 3011=SFI into T
this.Q |= 0x40 // set Q07F=hardware-induced SFI
this.Q &= ~(0x100); // reset Q09F=adder mode for R-relative addressing
} else {
if (this.L < 3) {
this.T = (this.P >>> (36-this.L*12)) & 0x0FFF;
this.L++;
} else {
this.T = this.P & 0x0FFF;
this.L = 0;
this.C++;
this.access(0x30); // P = [C]
}
}
} while (--this.Limit > 0);
}

View File

@@ -2,7 +2,7 @@
* retro-b5500/emulator Register.js
************************************************************************
* Copyright (c) 2012, Nigel Williams and Paul Kimpel.
* Licensed under the MIT Licensed, see http://www.opensource.org/licenses/mit-license.php
* Licensed under the MIT License, see http://www.opensource.org/licenses/mit-license.php
************************************************************************
* JavaScript object definition for the generalized Register prototype.
* Maximum register width is 52 bits, since Javascript stores numbers