ER[IOCOM]; *I = 155 TARGET[ILC]; %FOR IN-OUT INSTRUCTIONS THE OPCODE DETERMINES ONE OF TWO POSSIBLE DEVICES: 700 APR PI 712 TTY --- 776 UJMC (NO OTHER) 777 JMC (NO OTHER) THE TOP BIT OF AC SELECTS BETWEEN THE TWO DEVICES. THE LOW THREE BITS OF AC SELECT ONE OF 8 OPERATIONS: 0 BLKI 1 DATAI 2 BLKO 3 DATAO 4 CONO 5 CONI 6 CONSZ 7 CONSO NORMALLY I/O OPCODES BEGIN INTERPRETATION AT "IOD" WHICH SEARCHES AN SM TABLE FOR A MATCH ON THE LEADING 13 BITS OF THE INSTRUCTION AND SETS UP A DOUBLE DISPATCH. ALL INTERPRETED CONI'S RETURN WITH THE RESULT IN Q SO THAT CONI, CONSO, AND CONSZ MAY USE THE SAME SUBROUTINE. THE FINAL DISPATCHES FOR THESE ARE RESPECTIVELY, "WQTOP", "PAQES", AND "PAQNS". % ILLIO: Y_NULL; STACK_D, P_REFADR, GOTO[UUOM]; %THIS TABLE HAS THE DOUBLE DISPATCH FOR EACH I/O INSTRUCTION 3 BELOW THE OPCODE SO THAT Y DOES NOT HAVE TO BE BACKED UP AFTER THE MATCH IS DETECTED. THE ENTRY AT "IODEND" IS SET UP TO MATCH THE ONE BEING SEARCHED FOR SO THAT THE SEARCH LOOP NEEDN'T MAKE ANY END CHECK AND CAN RUN IN ONE CYCLE. % SM[XSLC,IP[IOTD]]; *"IOTD" DEFINED IN "PISYS" TARGET[XSLC]; E1[ILLIO], E2[SPUNT], E3[0]; E1[TTYCI], E2[PAQNS], E3[0]; E1[TTYCI], E2[PAQES], E3[0]; IODEND: E1[TTYCI], E2[WQTOP], E3[0]; *SEARCHED FOR OPCODE E1[TTYCO], E2[SPUNT], E3[1234]; *CONSO TTY = 71234 E1[RARG], E2[TTYDO], E3[1230]; *CONSZ TTY = 71230 E1[TTYDI], E2[SPUNT], E3[1224]; *CONI TTY = 71224 E1[PICI], E2[PAQNS], E3[1220]; *CONO TTY = 71220 E1[PICI], E2[PAQES], E3[1214]; *DATAO TTY = 71214 E1[PICI], E2[WQTOP], E3[1204]; *DATAI TTY = 71204 E1[PICO], E2[REMAPPC], E3[0074]; *CONSO PI = 70074 E1[RTOMDR], E2[WLITES], E3[0070]; *CONSZ PI = 70070 E1[APRCI], E2[PAQNS], E3[0064]; *CONI PI = 70064 E1[APRCI], E2[PAQES], E3[0060]; *CONO PI = 70060 E1[APRCI], E2[WQTOP], E3[0054]; *DATAO PI = 70054 E1[APRCO], E2[REMAPPC], E3[0034]; *CONSO APR = 70034 E1[RSWICH], E2[SPUNT], E3[0030]; *CONSZ APR = 70030 E1[SPUNT], E2[SPUNT], E3[0024]; *CONI APR = 70024 E1[SPUNT], E2[SPUNT], E3[0020]; *CONO APR = 70020 IODTAB: E1[SPUNT], E2[SPUNT], E3[0004]; *DATAI APR = 70004 TARGET[ILC]; *I = 10 IOD: LEFADR_P, P_INSTR, Q_MDR_377 777777S, POP, DGOTO[IODEND]; LPGRT_Q, PQ LCY [3], Y_NPC, SETSF[UM&J], POP, GOTO[.+1]; REFADR_P AND NOT Q, P_SY, GOTO[ILLIO,J=1]; Q_P AND Q, P_REFADR, CALL[UPQ]; SY_Q, Q_LPGRT, DGOTO[IODTAB]; *INSURE MATCH AT END Y_NPC, Q_P OR Q, GOTO[.+1]; P_(SY) U (MDR), P#Q, DECY, GOTO[.,ALU#0]; NPC_STACK_SY, Q_P_LEFADR, GOTO[WQTOP]; *MAPVA_P AT WQTOP DI[700,IOD,SPUNT,SPUNT]; DI[712,IOD,SPUNT,SPUNT]; %"GETPIA" IS CALLED WITH A MASK OF INTERRUPTS IN P. IT DETERMINES THE HIGHEST PRIORITY LEVEL FOR CONDITIONS IN THE MASK BY ANDING THE MASK WITH SUCCESSIVE ENTRIES IN IONTAB. THE PRIORITY LEVEL IS MERGED WITH THE CONTENTS OF "RTEMP" AND LEFT IN Q. "LEFADR" IS LEFT IN P. THIS ROUTINE IS USED BY THOSE CONI'S WHICH RETURN THE PRIORITY LEVEL OF THE DEVICE IN [E][41,43]. I = 7 % GETPIA: Y_IONTABX, LPGRT_P, DGOTO[5]; X_NPC, Q_RTEMP, INCY, GOTO[.+1]; Q_SY, INCY, RPGRT_Q; P AND Q, DECX, DGOTO[.,X>=0], P_RPGRT; GOTO[.+2,ALU#0], Q_SY, INCY, P_LPGRT, RPGRT_P+1; Q_RTEMP, P_LEFADR, RETURN; Q_RPGRT, P_LEFADR, RETURN; %"SETPIA" IS CALLED WITH THE DEVICE NO. FOR AN INTERRUPT IN Q AND Y AND WITH A PRIORITY LEVEL IN P[41,43]. IT IS USED BY THOSE CONO'S WHICH SET THE PIA FOR A DEVICE (PROVIDED INCMP=0). AT THE RETURN THE ORIGINAL CONTENTS OF P ARE IN "RPGRT2", THE PRIORITY LEVEL FOR THE DEVICE HAS BEEN SET TO P[41,43] AND THE PARAMETER (INTERRUPT LOCATION) HAS BEEN SET TO 40 + 2*P[41,43]. K IS CLOBBERED WITH THE SETTING OF THE "INCMP" FLAG AND THE ABOVE CHANGES DO NOT TAKE PLACE IF INCMP=1. RPGRT3, RTEMP, LPGRT, LPGRT2, RPGRT, AND STEMP1 ARE CLOBBERED I = 6 % SETPIA: RPGRT2_LPGRT_P, P_INTTAB; MDR_P+Q, SETSF[INCMP&K], P_RPGRT2; P_2P, BAMASK[4], Q_40S, RETURN[K=1]; RTEMP_P+Q, Q_SY, P_LPGRT, BAMASK[3]; RPGRT3_Q, CALL[SPILEV], STEMP1_MDR; Y_STEMP1, GOTO[SETPARAM]; *THE FOLLOWING ROUTINES IMPLEMENT THE APR IN-OUT INSTRUCTIONS *I = 60 RSWICH: READ_NULL, CALL[RETN]; *DATAI APR READS THE SIMULATED SWITCHES Q_MDR, GOTO[WQTOP]; %THE ENABLING AND DISABLING OF THE VARIOUS INTERRUPT CONDITIONS FOR THE APR AND PI SYSTEM IS KEPT TRACK OF AS FOLLOWS: "NOTFCOND" CONTAINS 0'S ONLY IN THOSE BITS CORRESPONDING TO OVF, FOVF, AND PDOVF IN THE F REGISTER AND ONLY WHEN THOSE INTERRUPTS ARE ENABLED (PDOVF ALWAYS ENABLED). "APRPIMCOND" CONTAINS 1'S ONLY IN THOSE BITS CORRESPONDING TO POWFB, PARITY, CLKB, AND NXM IN [MICINTS] AND ONLY WHEN THE CORRESPONDING CONDITION IS ENABLED FOR INTERRUPTS (POWFB AND NXM ARE ALWAYS ENABLED). THE PARITY ERROR INTERRUPT IS ENABLED/DISABLED BY CONO PI AND THE CLOCK, FOVF, AND OVF INTERRUPTS BY CONO APR. BOTH CONO'S CALL "SPILEV" WHICH RECONSTRUCTS INTERRUPT CONDITIONS. HOWEVER, ATTEMPT TO ENABLE/DISABLE ANY OF THE INTERRUPT CONDITIONS RESULTS IN AN ILLEGAL INSTRUCTION TRAP WHEN INCMP = 1. NOR ARE THE INTERRUPT LOCATIONS OR PI LEVELS CHANGED WHEN INCMP=1. (THE ONLY USEFUL FUNCTION OF CONO APR IS THEN CLEARING PDOVF, FOVF, AND CLOCK, WHICH CAN ALSO BE ACCOMPLISHED BY THE CLRIR JMC. FOVF AND OVF NOW AND SOMEDAY PDOVF ARE SETTABLE BY JRSTF ALSO. % SM[NXM,IP[200000 000000S]]; SM[PARITY,IP[100000 000000S]]; SM[CLKB,IP[400S]]; ***DEPARAMETERIZED TO MERGE CONSTANTS. CLKB IS IN NVMAX. SLC[(DBLSAP: E1[0], E2[SAP1], E3[SAP1])]; APRCO: RTEMP_P, Q_400000S, DGOTO[SAP1]; *RTEMP HOLDS E P AND Q, Q RSH 1, READ_DLSBS, CALL[.+1]; CLEARFC[PDOVF,ALU#0], P AND Q; CALL[IORESET,ALU#0], P_DLSOD_MDR, LPGRT2_A1; P_RTEMP, Q_10000S; P AND Q, Q RSH 1, STACK_DBLSAP; GOTO[.+2,ALU=0], P AND Q, Q RSH 1, SETSF[INCMP&K]; LTEMP_Q, FRZBALUBC, Q_NXM, CALL[CLRMINT]; *CLEAR NXM CALL[DISCLK,ALU#0], P AND Q, Q RSH 1; CALL[ENCLK,ALU#0], P AND Q, Q RSH 1; GOTO[.+2,ALU=0], P AND Q, Q RSH 1; LTEMP_Q, FRZBALUBC, Q_CLKB, CALL[CLRMINT]; *CLEAR CLK CALL[DISFOV,ALU#0], P AND Q, Q RSH 1; CALL[ENFOV,ALU#0], P AND Q, Q RSH 1; CLEARFC[FOVF,ALU#0], P AND Q, Q RSH 1; ***CLEAR FUNF ALSO?? CALL[DISOV,ALU#0], P AND Q, Q RSH 1, X_4S; CALL[ENOV,ALU#0], P AND Q, PQ LCY [1], XMASK, Q_40S; MDR_P, CLEARFC[OVF,ALU#0]; APRLEV_MDR, GOTO[REMAPPC,K=1]; *ENTRY HERE WITH 40 IN Q, 2*PI LEVEL IN P, AND K=INCMP. *ALSO ENTER HERE FROM CONO PI. SAP: RTEMP_P+Q, Q_APRINTS, PQ RCY [1], GOTO[CONINTCOND,K=1]; RPGRT3_Q, Q_NOTFCOND; Q_(NOT Q) U (APRPIMCOND), CALL[SPILEV]; Y_CLKDV, CALL[SETPARAM]; *CLOCK Y_PDLDV, CALL[SETPARAM]; *PUSH DOWN OVERFLOW Y_OVFDV, CALL[SETPARAM]; *OVF *GO THROUGH INSTR. BELOW TWICE FOR "PICO", FOUR TIMES FOR "APRCO" SAP1: DECY, GOTO[SETPARAM]; *NXM, PARITY, FOVF, POWFAIL DISPAR: LTEMP_Q, FRZBALUBC, GOTO[DISMINT,K=0], Q_PARITY; DISCLK: LTEMP_Q, FRZBALUBC, Q_CLKB, GOTO[ILLIO,K=1]; DISMINT: P_APRPIMCOND, FRZBALUBC, CALL[CLRPQ], RPGRT_P; AP1: APRPIMCOND_Q, FRZBALUBC, P_RPGRT, Q_LTEMP, RETURN; ENPAR: LTEMP_Q, FRZBALUBC, Q_PARITY, GOTO[ENMINT,K=0]; ENCLK: LTEMP_Q, FRZBALUBC, Q_CLKB, GOTO[ILLIO,K=1]; ENMINT: P_APRPIMCOND, FRZBALUBC, RPGRT_P; Q_P OR Q, FRZBALUBC, GOTO[AP1]; DISOV: LTEMP_Q, FRZBALUBC, Q_OVF, GOTO[NAP0,K=0]; DISFOV: LTEMP_Q, FRZBALUBC, Q_FOVF, GOTO[ILLIO,K=1]; NAP0: P_NOTFCOND, FRZBALUBC, CALL[UPQ], RPGRT_P; NAP1: NOTFCOND_Q, FRZBALUBC, P_RPGRT, Q_LTEMP, RETURN; ENOV: LTEMP_Q, FRZBALUBC, Q_OVF, GOTO[NAP2,K=0]; ENFOV: LTEMP_Q, FRZBALUBC, Q_FOVF, GOTO[ILLIO,K=1]; NAP2: P_NOTFCOND, FRZBALUBC, RPGRT_P; Q_P AND NOT Q, FRZBALUBC, GOTO[NAP1]; %CONI APR GET SET AS FOLLOWS: 23 PDOVF (FROM F) 24 USER IN-OUT N.I. 25 ADDRESS BREAK N.I. 26 MEMORY PROTECTION N.I. 27 NXM (FROM MICINTS) 31 CLKINTEN (FROM APRPIMCOND) 32 CLOCK FLAG (FROM MICINTS) 34 FOVFINTEN (FROM NOTFCOND) 35 FOVF (FROM F) 36 TRAP OFFSET N.I. 37 OVFINTEN (FROM NOTFCOND) 40 OVF (FROM F) 41-43 PIA BY "GETPIA" SUBR % MC[PDOVF&G,PDOVF,G]; MC[FOVF&H,FOVF,H]; MC[OVF&J,OVF,J]; APRCI: P_MICINTS, DGOTO[400], RTEMP_A0; Q_NPC, SETSF[OVF&J], GOTO[.+1]; *CLKB=400 P AND Q, Q_NXM; P AND Q, Q_1000S, P_RTEMP, CALL[PQORP,ALU#0]; *CLOCK? Q_10000S, CALL[PQORP,ALU#0], LTEMP_Q; *NXM? SAVE 1000 TO GENERATE CLKB BELOW ***NOTE THAT THE INTERRUPTS WILL BE READ AS "ENABLED" EVEN THOUGH APR IS ***ASSIGNED PI CHANNEL 0. Q_APRPIMCOND, P_(LTEMP) RSH [1]; *(LTEMP) RSH 1 = 400 = CLKB P AND Q, P_NOTFCOND; LPGRT2_P, Q_2000S, CALL[PQORP,ALU#0], P_RTEMP; *CLOCK ENABLED? Q_20S, CALL[PQORP,ALU>=0]; *OVF ENABLED (KNOW OVF IS DEVICE 0) P_LPGRT2, Q_FOVF, DGOTO[200]; P AND Q, SETSF[PDOVF&G], Q_NPC, GOTO[.+1]; SETSF[FOVF&H], CALL[PQORP,ALU=0], P_RTEMP; *FOVF ENABLED? Q_200000S, CALL[PQORP,G=1]; *PDOVF? CALL[PQORP,H=1], Q_100S; *FOVF? Q_10S, CALL[PQORP,J=1]; *OVF? P_APRINTS, GOTO[GETPIA]; *THE FOLLOWING ROUTINES IMPLEMENT THE PI IN-OUT INSTRUCTIONS *I = 31 WLITES: WRITE_1S, GOTO[REMAPPC]; *PRECEDED BY "RTOMDR". SIMULATE LITES %CONO PI REQUIRES EMULATION OF: 22 CLEAR POWER FAILURE (IN MICINTS) 23 CLEAR PARITY ERROR (IN MICINTS) 24 DISABLE PARITY ERROR INTERRUPT (APRPIMCOND AND IONTAB) 25 ENABLE PARITY ERROR INTERRUPT (APRPIMCOND AND IONTAB) 27 CLEAR PI SYSTEM (DEACTIVATE PI SYSTEM, ELIMINATE ALL INTERRUPT REQUESTS WHICH HAVE BEEN ACCEPTED BUT ARE STILL WAITING, AND DISMISS ALL INTERRUPTS THAT ARE CURRENTLY BEING HELD) 30 INITIATE INTERRUPT ON CHANNELS 31 TURN ON CHANNELS (N.I.) 32 TURN OFF (N.I.) 33 DEACTIVATE PI SYSTEM (CLEARS PIACTIVE) 34 ACTIVATE PI SYSTEM (SETS PIACTIVE) 35,43 CHANNELS AFFECTED BY E[30,32] % SM[POWFB,IP[10000 000000S]]; ***IN MICINTS. DEPARAMETERIZED TO MERGE CONSTANTS PICO: RTEMP_P, Q_400000S, DGOTO[SAP1]; P AND Q, Q RSH 1, SETSF[INCMP&K], CALL[.+1]; P AND Q, MDR_400S, GOTO[.+2,ALU=0], Q RSH 1; CALL[CLRMINT], LTEMP_Q, FRZBALUBC, Q_POWFB; P AND Q, GOTO[.+2,ALU=0], Q RSH 1; CALL[CLRMINT], LTEMP_Q, FRZBALUBC, Q_PARITY; P AND Q, CALL[DISPAR,ALU#0], Q_10000S; P AND Q, CALL[ENPAR,ALU#0], Q RSH 1; P AND Q, CALL[PIRESET,ALU#0], CLEARFC[PIACTIVE&G,ALU#0], Q_MDR; *Q_400 P AND Q, CALL[INITI,ALU#0], Q RSH 1; P AND Q, CLEARFC[PIACTIVE&G,ALU#0], Q RSH 1; SETFC[PIACTIVE&G,ALU#0], Q RSH 1; *Q_40 P_APRLEV, GOTO[SAP,K=0]; POP, GOTO[CONINTCOND]; *** TURN-OFF ALL CHANNELS IS NOT EMULATED. *IT SHOULD NOT BE EMULATED BY TURNING OFF ALL DEVICES PIRESET: MICINTS_NULL; *TURN OFF REQUESTS WHICH HAVE BEEN ACCEPTED PISTAT_NULL, RETURN; *DISMISS INTERRUPTS BEING HELD *INITIATE INTERRUPTS ON LEVELS IN P[35,43] INITI: P_NULL, Q_RTEMP, SETF[MICRO]; PQ RCY [14], BAMASK[37], Q_400S; MDR_(P) U (MICINTS), P_RTEMP, INHINT; MICINTS_MDR, P AND Q, Q RSH 1, RETURN; %THE INFORMATION FOR CONI PI IS GOTTEN AS FOLLOWS: 22 POWER FAILURE (MICINTS) 23 PARITY ERROR (MICINTS) 24 PARITY INTERRUPT ENABLED (APRPIMCOND) 25-33 INTERRUPT IN PROGRESS ON CHANNELS (PISTAT) 34 PIACTIVE (F) 35-43 CHANNELS ON (177) % PICI: Q_PISTAT, P_A1, BAMASK[7]; *ALL 7 CHNLS ON Q_P, PQ RCY [34], BAMASK[17], SETSF[PIACTIVE&G]; *PISTAT[34,43] INTO P[25,33] RTEMP_P_P OR Q, Q_200S, CALL[PQORP,G=1]; *PIACTIVE=200 Q_MICINTS, 0Q RCY [12]; *PARITY=100000 000000 P AND Q, PQ RCY [2], BAMASK[37]; *POWFAIL=20000 000000 P AND Q, P_RTEMP, Q_200000S, CALL[PQORP,ALU#0]; Q LSH 1, CALL[PQORP,ALU#0]; *KNOW POWFAIL=400000=PARITY LSH 1 Q_APRPIMCOND, 0Q RCY [24]; *PARITY BIT IS 100000 000000 P AND Q, PQ RCY [22], BAMASK[20]; P_RTEMP, Q_P, CALL[PQORP,ALU#0]; Q_P, P_LEFADR, RETURN; *THE FOLLOWING IMPLEMENT THE CONSOLE TELETYPE *I = 41 %CONI TTY IS EMULATED AS FOLLOWS: 30 TEST (N.I.) 35 INPUT BUSY (N.I.) 36 INPUT DONE IFF [DLSIN]<0 37 OUTPUT BUSY IFF TTYBSY=1 AND [DLSOD]>=0 40 OUTPUT DONE IFF [DLSOD]<0 PIA USING "GETPIA" ROUTINE % TTYCI: READ_DLSOD, REFADR_P, CALL[RETN]; P_RTEMP_A0, SETSF[TTYBSY&K], Q_MDR; AQ, Q_10L, CALL[PQORP,B<0], CLEARFC[TTYBSY&K,B<0]; READ_DLSIN, FRZBALUBC; Q_20S, FRZBALUBC, CALL[PQORP,K=1]; P_MDR, Q LSH 1, DGOTO[.+3,ALU#0]; P_RTEMP, CALL[PQORP,B<0], P; Q_DLSINT, CALL[CLRMINT,ALU=0]; P_DLSINT, GOTO[GETPIA]; %CONO TTY IS EMULATED AS FOLLOWS: 30 TEST (N.I.) 31 CLEAR INPUT BUSY (N.I.) 32 CLEAR INPUT DONE 33 CLEAR OUTPUT BUSY 34 CLEAR OUTPUT DONE (ALSO CLEARS OUTPUT BUSY) 35 SET INPUT BUSY (N.I.) 36 SET INPUT DONE 37 SET OUTPUT BUSY (ALSO SETS OUTPUT DONE) 40 SET OUTPUT DONE 41-43 PIA % TTYCO1: RMW_DLSOD, INHINT, FRZBALUBC; CLRS: LTEMP_Q, FRZBALUBC, Q_400000 000000S, CALL[PMDR]; MDR_P AND NOT Q, P_RPGRT2, Q_LTEMP, WRESTART, FRZBALUBC, GOTO[RETN]; SETS: SETSF[J], FRZBALUBC; LTEMP_Q, Q_(MDR) U (400000 000000S), FRZBALUBC; WRESTART, MDR_Q, Q_LTEMP, FRZBALUBC, RETURN; TTYCO: Q_Y_DLSDV, CALL[SETPIA]; P_RPGRT2, Q_1000S, POP; *J WILL WIND UP 0 IFF EITHER INPUT OR OUTPUT DONE IS SET P AND Q, Q RSH 1, POP, SETF[J]; P AND Q, GOTO[.+2,ALU=0], Q RSH 1; RMW_DLSIN, INHINT, FRZBALUBC, CALL[CLRS]; CLEARFC[TTYBSY&K,ALU#0], P AND Q, Q RSH 1; CALL[TTYCO1,ALU#0], CLEARFC[TTYBSY&K,ALU#0], Q RSH 1; P AND Q, Q RSH 1; P AND Q, Q RSH 1, GOTO[.+2,ALU=0]; RMW_DLSIN, INHINT, FRZBALUBC, CALL[SETS]; P AND Q, SETFC[TTYBSY&K,ALU#0], GOTO[.+2,ALU#0]; GOTO[.+2,ALU=0]; RMW_DLSOD, INHINT, CALL[SETS]; Q_DLSINT, RETURN[J=1]; *JUMP HERE FROM IOCK QMIC: Q_(MICINTS) U (Q), INHINT; *JUMP HERE FROM DISK STUFF KPIS1: P_RINT, MICINTS_Q, RETURN; TTYDO: RPGRT2_P, RMW_DLSOD, INHINT, CALL[CLRS]; *TURN-OFF OUTPUT DONE P_DLSB, POP, Q_RPGRT2; WRITE_P+1, PQ RCY [20], SETSF[G], DGOTO[.+2]; MDR_P, SETF[TTYBSY&K], CALL[RETN]; RMW_DLSO, INHINT, CALL[CLRS]; X_25S, GOTO[SIGNAL]; TTYDI: RMW_DLSIN, INHINT, REFADR_P, CALL[CLRS]; READ_DLSB, CALL[TPMDR]; PQ RCY [24], BAMASK[10]; Q_P, P_REFADR, GOTO[WQTOP];