ER[JMC]; *I = 191 TARGET[ILC]; *! MAXC1 ONLY SV[XPARITY,2160]; *DISK INTERRUPT CHANNELS *! *~ MAXC2 ONLY SV[XPARITY,200 002160]; *DISK INTERRUPTS & PARITY (700 002160 DOESN'T WORK) *~ %FOR THE IN-OUT RESET ROUTINE, "KRESET" TURNS OFF ALL THE DISK UNITS BY "KOFF" (BUT DOES NOT RECALIBRATE). I = 4 % DECX, RETURN[X<0]; KRESET: KUNIT←X, DGOTO[.-1], LTEMP←A1; CALL[.+1,X>=0], YKPTR←X, INHINT; KSET←KOFFX, KNEWCOMM, INHINT, GOTO[.+3]; **NO KRDYW %"KOFF" IS A JMC WHICH: 1. TURNS OFF SECTOR MICROINTERRUPTS, DISMISSES WORD INT., CLEARS ERRORS, AND RECALIBRATES UNIT 2. CLEARS THE INTERRUPT REQUEST BIT IN MICINTS FOR THIS UNIT 3. MAXKA←NULL (SO THAT "KGO" AND "KSEEK" WILL BE REJECTED) 4. WIDISP←CRASH (SO THAT FALSE DISPATCH INTS WILL CRASH) 5. WCSA←NULL (SO THAT FALSE READ AND WRITE INTS WILL WRITE A HARMLESS LOCATION AND CRASH) 6. NSDISP←NULL (SO THAT FALSE SECTOR INTS WILL CRASH) 7. DESELECT THE UNIT AT CALL: KUNIT←UNIT NO. HAS BEEN DONE I = 10 % KOFF: X←KUNIT; KSET←KOFFL, KNEWCOMM, INHINT; ***NO KRDYW P←LTEMP, AMASK[30], MAXKA←KMDR←NULL, DGOTO[SCRASH]; WIDISP←NPC, P←P+1, INHINT, GOTO[.+1]; Q←KSTAT, A1, DGOTO[.+1]; *CHECK "DESEL" TO SEE IF A UNIT IS REALLY THERE, ELSE "KRDYW" WILL HANG P AND Q, WCSA←NULL, INHINT, CALL[KRDYW,ALU=0]; KSET←DESEL, KNEWCOMM, INHINT; P←A1, XMASK, INHINT, Q←MICINTS; P←P+1, KA←KWDATA, DGOTO[SCRASH]; Q←NOT P AND Q, INHINT, NSDISP←NPC, GOTO[KPIS1]; %"PKSER" IS A SUBROUTINE TO LOOK AT EACH OF THE DISK UNITS AND DECIDE ON WHICH UNIT A PARTICULAR DISK PACK IS MOUNTED. AT CALL: PACK NO. IN RTEMP[12,21], 7 IN X. AT RETURN: Y POINTS TO THE 16-WORD UNIT ARRAY FOR THE PACK AND KUNIT POINTS TO THE UNIT, MAXKA IN Q, P PRESERVED. IF THE PACK IS OFF-LINE, THE ILLEGAL PACK BIT IS RETURNED IN AC, AND AN IMMEDIATE EXIT IS MADE. I = 5 % PKSER: LPGRT←P, YKPTR←KUNIT←X, P←777777R; Q←MAXKA, P←NOT P, BAMASK[32]; Q←P AND Q, P←RTEMP, DECX, DGOTO[QTOAC,X<0]; P#Q, Q←ILLPK, DGOTO[PKSER]; RETURN[ALU=0], P←LPGRT, Q←MAXKA; %"KON" IS ENTERED WITH THE MAXIMUM LEGAL DISK ADDRESS IN AC FOR UNIT E. IT RESETS THAT UNIT AND PUTS IT ON-LINE. IF THE UNIT IS ALREADY ON LINE IT SERVES TO RESET THE UNIT AS FOLLOWS: 1. NSDISP←INTRET; 2. ENABLE SECTOR INTERRUPTS AND CLEAR ERRORS 3. MAXKA←Q 4. CMMA←NMMA←USTATE←0 5. ENABLE THE DISK MICROINTERRUPT CHANNELS 6. KA←PACK,,7770 KBLK AND KPARAM SHOULD BE SET IN ADVANCE BY THE SLOC JMC THERE ARE NO ERRORS. KON ALWAYS SKIPS. I = 7 % *YKPTR←KUNIT←E WAS DONE BY JMC DISPATCH INSTRUCTION KON: MAXKA←Q, P←LTEMP, AMASK[14], DGOTO[INTRET]; Q←P OR Q, NSDISP←NPC, INHINT, GOTO[.+1]; KSET←SECERRS, KNEWCOMM, INHINT; ARM←XPARITY, INHINT; CMMA←KMDR←NULL, P←LTEMP, AMASK[3], DGOTO[KSEC2]; USTATE←KWDATA, Q←NOT P AND Q, DGOTO[.+1]; NMMA←NULL, GOTO[ASKIP]; %"KNOPDP" TURNS OFF THE PDP-10 PORTION OF DISK INTERRUPTS ON THE PACK SELECTED BY AC. ERROR RETURN IF THE PACK NUMBER ISN'T FOUND OR UNIT BUSY. OTHERWISE, NSDISP←@INTRET AND SKIP RETURN. AT CALL: PACK NUMBER IN Q, 377 000000 IN P I = 5 % KNOPDP: RTEMP←P AND Q, X←7S, CALL[PKSER]; MDR←NMMA, DGOTO[KNOP1]; P←(MDR) U (CMMA), DGOTO[INTRET]; CRJ: Q←ILLOP; *COMMAND REJECT *! MAXC 1 ONLY ILLRET: Q←(KSTAT) U (Q) U (USTATE), GOTO[QTOAC]; *! *~ MAXC 2 ONLY ILLRET: P←KSTAT; Q←(P OR Q) U (USTATE), GOTO[QTOAC]; *~ %"KSEEK" IS USED TO INITIATE A SEEK AND ENABLE PDP-10 INTERRUPTS. ERROR RETURNS WITH STATUS IN AC ARE GIVEN FOR: 1. PACK NO. NOT ON-LINE 2. ILLEGAL ARM POSITION 3. SEEKING TO A DIFFERENT ARM POSITION ALREADY 4. HARDWARE FAILURE OTHERWISE, A SKIP RETURN IS GIVEN. AT ENTRY: DISK ADDRESS (PACK AND ARM) IN Q AND IN AC, 377 000000 IN P I = 21 % KSEEK1: P←(MDR) U (CMMA), DGOTO[KSERV]; KNOP1: P, Q←NPC, GOTO[.+1]; P←PC, GOTO[ASKIP1,ALU#0]; *BUSY? NSDASK: NSDISP←Q, GOTO[ASKIP]; KSEEK: RTEMP←P AND Q, P←7770S; LTEMP←P AND Q, X←7S, CALL[PKSER]; *LTEMP←NEW ARM POSITION RTEMP←P AND Q, Q←KA; *RTEMP←MAX. ARM POS. P←P AND Q, Q←LTEMP, MDR←NMMA; *P←CURRENT ARM POS. P#Q, P←RTEMP,INHINT; *SEEK TO CURRENT POS. ENABLES PDP-10 INTERRUPTS IFF THEY ARE OFF P-Q, PQ RCY [33], Q←KSTAT, GOTO[KSEEK1,ALU=0]; *CHECK FOR LEGAL ARM POSITION GOTO[.+2,ALU>=0], RPGRT2←P, P←NOSKER; Q←ILLARM, GOTO[ILLRET]; *CHECK FOR HARDWARE ERRORS OR SEEKING P AND Q, P←(MDR) U (CMMA); P, P←KA, INHINT, GOTO[ILLRET,ALU#0]; *SECTOR INTERRUPTS TABOO WHILE UPDATING KA USTATE←NULL, INHINT, GOTO[CRJ,ALU#0]; Q←(NOT P) U (7770S), P←LTEMP, DGOTO[KSERV]; Q←P OR NOT Q, P←RPGRT2, NSDISP←NPC, GOTO[.+1], INHINT; KA←Q, Q←P, CALL[KRDYW], INHINT; *LOAD CYLINDER REGISTER (MUST CALL KRDYW BECAUSE OF SECTOR INTS) *(KNOW (LOADC) WILL BE F1 = READS WHICH = KNEWCOMM) *USE "FSET" PURELY AS A GARBAGE ROUTINE TO ALLOW INTERRUPTS WHILE WAITING KSET←(Q) U (LOADC), INHINT, CALL[FSET]; INHINT, CALL[KRDYW]; KSET←SEEK, KNEWCOMM, INHINT, GOTO[ASKIP]; %"KGO" IS USED TO INITIATE ALL DATA TRANSFERS. IT CAN BE ISSUED AT ANY TIME AND NOTHING BAD WILL HAPPEN IF A SECTOR MICROINTERRUPT OCCURS IN MEDIAS RES. THE ADDRESS OF THE 9-WORD COMMAND BLOCK IS IN P. ERROR RETURNS WITH STATUS IN AC ARE GIVEN FOR: 1. MAIN MEMORY ADDRESS < 20 2. PACK NOT ON-LINE 3. ARM # CURRENT ARM POSITION OR SECTOR # NEXT SECTOR 4. ILLEGAL HEAD SELECT 5. ILLEGAL OPERATION # AT CALL: Q CONTAINS VIRTUAL ADDRESS OF A DISK DATA TRANSFER COMMAND FOR WHICH MAPVA←P←AQ, SAMASK[22] HAS JUST BEEN DONE. A SKIP RETURN IS GIVEN IF THE COMMAND IS ACCEPTED. EACH COMMAND DISPATCH WORD CONTAINS AN INITIAL COMMAND DISPATCH IN B[30,43] AND 6 4-BIT BYTES IN B[0,27] CONTROLLING THE PATH OF THE DISK FINITE STATE MACHINE (SEE "DISPT" TABLE IN KINT) I = 13 % F[FL,0,3]; F[FM,4,7]; F[FN,10,13]; F[FO,14,17]; F[FP,20,23]; F[FQ,24,27]; M[KOP,XSLC[E1[#1]FL[#2]FM[#3]FN[#4]FO[#5]FP[#6]FQ[#7]]]; SM[XSLC,IP[KCOMS]]; *BEGINNING OF COMMAND DISPATCH TABLE (10 WORDS) KOP[CSW,15,3]; *WRITE HEADER KOP[CSW,15,4,12,4,13,3]; *WRITE, WRITE, WRITE KOP[CSR,10,0,5,2]; *READ, READ KOP[CSR,10,1,12,3]; *READ, WRITE KOP[CSR,10,0,5,0,7,2]; *READ, READ, READ KOP[CSR,10,0,6,0,7,2]; *READ, COMPARE, READ KOP[CSR,10,0,5,1,13,3]; *READ, READ, WRITE KOP[CSR,10,0,6,1,13,3]; *READ, COMPARE, WRITE KOP[CSR,10,1,12,4,13,3];*READ, WRITE, WRITE KOP[CSR,10,0,6,0,14,2]; *READ, COMPARE, CHECK SV[KPREH,777400 000000]; *LEADING BITS OF DISK HEADER ***ERROR IF NOT RESIDENT PAGE, BUT NOT NECESSARILY IN MAP KGO: CALL[RQARG]; *Q←COMMAND AND DISK ADDRESS Q←(Q) U (KPREH), QQ RCY [33], DGOTO[KCOMS]; RPGRT2←Q, Q←NPC, PQ RCY [0], SAMASK[4], GOTO[.+1]; *RPGRT2←DISK HEADER *COMMAND REJECT ERROR IF G=1 (COMMAND BLOCK IN AC) Y←P+Q, P←RPGRT2, SAMASK[22], GOTO[CRJ,G=1]; *Y←OPER. CODE + KCOMS LPGRT←P, Q←SY, GOTO[CRJ,Y>=0]; *Y-REG. OVF IF COMMAND NO. > 11 LPGRT2←Q, Q←RPGRT2, P←377 000000S; *LPGRT2←NSDISP VALUE RTEMP←P AND Q, P←LPGRT, X←7S, CALL[PKSER]; Q←P, P←Q, BAMASK[22], MDR←ILLHD; P-Q, P←RPGRT2, Q←KA, INHINT; *MUST TURN-OFF INTS. DURING VOLATILE PART GOTO[ILLRET,ALU<0], P←P#Q, SAMASK[14], Q←MDR, INHINT; *KNOW SECTOR AND ARM ARE RIGHT-MOST FIELDS OF ADDRESS P, NMMA←MAR, Q←RPGRT2, DGOTO[NSDASK]; NKA←Q, Q←LPGRT2, P←777777R, AMASK[7], INHINT, GOTO[.+1,ALU#0]; NMMA←NULL, Q←P+1, GOTO[ILLRET]; *Q←200 = SECNE *ASSIGN DEVICE X[36,43] TO PRIORITY LEVEL P[41,43], -1 IN RTEMP ASNLEV: LTEMP←P, Q←FINTS, P←RTEMP, XMASK; RPGRT3←P←P+1, FRZBALUBC, DGOTO[.+3,ALU=0]; P←P AND Q, Q←NOTFCOND, CALL[UPQ,ALU=0]; Q←NOT P AND Q; *ENABLE FCOND NOTFCOND←Q, Q←RPGRT3, P←LTEMP, GOTO[SPILEV]; *ASSIGN AC[14,43] TO BE VALUE OF INTERRUPT PARAMETER FOR DEVICE [P] ASNLOC: P-Q, Q←INTTAB, DGOTO[SETPARAM]; GOTO[ILLIO,ALU>=0], Y←P+Q; *ASSIGN BOTH LEVEL AND LOCATION FOR DEVICE ALEVLOC: LTEMP←P←P, SAMASK[6], CALL[ASNLOC]; P←LTEMP, RTEMP←A1, GOTO[ALEVX]; %*READ LEVEL INTO AC[0,13] AND PARAMETER INTO AC[14,43] FOR DEVICE [P] *DEIMPLEMENTED FOR BYTE LISP. JMC DISPATCH WAS Q←INTTAB, GOTO[RLEVLOC] RLEVLOC: X←P; Y←P+Q, P←RTEMP, XMASK; *Y←INTTAB+DEV NO. Q←SY, P←LTEMP, BAMASK[30], RTEMP←P+1; LAC←P AND Q, Y←IONTABX, DGOTO[6]; X←NPC, Q←A0, P←LAC, INCY, GOTO[.+1]; Q←SY, LAC←P+Q, INCY, P←RTEMP, RETURN[ALU#0]; P AND Q, DECX, P←LAC, Q←100 000000S, GOTO[.-1,X>=0]; P←LAC, SAMASK[30], GOTO[PTOAC]; % *SUBROUTINE FOR "SETIR" AND "CLRIR" IOCK: P←A1, XMASK, Q←FINTS; Q←P+1, P←Q, SETFC[MICRO,G=1]; MDR←P AND Q; STEMP←MDR; SETFB[STEMP,G=1], GOTO[QMIC,G=1]; *SETF AND GO FOR "SETIR", CLEARF FOR "CLRIR" %ROUTINE ENTERED WITH BITS IN MICINTS TO CLEAR IN Q, VALUES TO BE RESTORED TO P AND TO Q IN RTEMP AND LTEMP, RESPECTIVELY. BALUBC DOESN'T CHANGE. % CLRMINT: P←MICINTS, FRZBALUBC, CALL[CLRPQ], INHINT; MICINTS←Q, Q←LTEMP, P←RTEMP, FRZBALUBC, RETURN; *HERE WITH FINTS IN P *! MAXC1 ONLY READIR: Q←NOT F; LTEMP←P AND NOT Q, Q←MICINTS; *! *~ MAXC2 ONLY READIR: Q←FLAGS; LTEMP←P AND Q, Q←MICINTS; *~ P←NOT P AND Q, Q←LTEMP, GOTO[POQA]; *0 THE BIT FOR DEVICE [X] IN MAXNV AND SIGNAL THE NOVA SIGNAL: P←A1, XMASK, RMW←MAXNV, INHINT, CALL[RETN]; Q←P+1, P←MDR, SIGNOVA, GOTO[PANQM]; *ENABLE/DISABLE INTERRUPTS ON PI LEVELS SELECTED BY E[35,43] LEVX: PQ RCY [35], AMASK[16], Q←PISTAT, CALL[UPQ,J=1]; Q←NOT P AND Q, PISTAT←Q, GOTO[CONINTCOND,J=1]; PISTQ: PISTAT←Q, GOTO[CONINTCOND]; MC[TTYBSY&K,TTYBSY,K]; *DLS VARIABLES SVN[DLSOD]; SVN[DLSO]; SVN[DLSIN]; SVN[DLSB]; *RESET APR, PI, MAP, AND DISKS. DON'T CLOBBER Q, LPGRT3 PRES: X←RESCNT, RTEMP←Q, DGOTO[SLMIC]; Y←NPC, CLEARF[-1S], INHINT, GOTO[.+1]; ARM←NULL, INHINT, CALL[IREAD]; Y←INTTAB, DGOTO[52]; X←NPC, GOTO[.+1]; P←IMINTT, CALL[IREAD]; PRES1: X←7S, CALL[KRESET]; ***WAIT FOR DISK ACTIVITY TO CEASE??? SETF[IENABLE], GOTO[MAPRESET]; *RETURN "RTEMP" IN Q %IORESET CLEARS THE CONTROL LOGIC IN ALL PERIPHERAL EQUIPMENT BUT DOES NOT AFFECT THE PRIORITY INTERRUPT SYSTEM OR PROCESSOR FLAGS. IT ALSO MUST RELOAD ALL INTER-PROCESSOR COMMUNICATION VARIABLES WHICH ARE POINTERS. ***MUST NOT CLOBBER "RTEMP" OR "STEMP1" % RESIO: P←DLSOD←MDR; IORESET: P←Q←P+1, CLEARF[TTYBSY&K], DGOTO[.+1]; DLSO←Q, P←Q←P+1; DLSIN←Q, Q←P+1, P←LPGRT2, BAMASK[24]; *P←IORESET BIT -1 DLSB←Q, LPGRT2←P+1; *CLEAR ALL INTS EXCEPT OVF, NXM, PARITY, FOVF, POWFL, PDLOVF Q←17757 777777S, CALL[CLRMINT]; WRITE←MAXNV, SIGNOVA, Q←LPGRT2, DGOTO[PRES1]; MDR←P←NOT Q, CALL[SPUNT]; *READ "LOGF" INTO AC[23], "INCMP" INTO AC[24], NOT "PIACTIVE" *INTO AC[25], PI LEVELS OFF INTO AC[26,34], AND PI-IN-PROG INTO AC[35,43] PIREAD: P←PISTAT, Q←P+1, CALL[PQORP,K=1]; SETSF[PIACTIVE&G], DGOTO[PIRDX]; Q RSH 1, SETSF[LOGF&K], CALL[PQORP,G=0]; %SET VALUE OF SYSTEM PARAMETER: 0 TO SLOCLOW-1 ARE IN SM TABLE, 413 + 20*UNIT AND 414 + 20*UNIT ARE "KBLK" AND "KPARAM" FOR THE DISK UNITS RESPECTIVELY. OTHER VALUES BETWEEN 400 AND 577 ARE RESERVED FOR MORE DISK PARAMETERS. % SETSYSP: P-Q, Q←400S; P-Q, Q←600S, GOTO[SETSYS1,ALU<0]; *0 TO SLOCLOW-1? P-Q, Q←13S, GOTO[ILLIO,ALU<0]; *400-577? Y←P, SAMASK[4], GOTO[ILLIO,ALU>=0]; P#Q, Q←14S; P#Q, Q←LAC, GOTO[QTOSY,ALU=0]; *KBLK? GOTO[ILLIO,ALU#0]; *KPARAM? QTOSY: SY←Q, RETURN; SETSYS1: DGOTO[SLMIC]; Q←NPC, GOTO[.+1]; Y←P+Q, Q←LAC, GOTO[QTOSY]; *WRITE ABSOLUTE ADDRESS WABS: MDR←Q, RETURN; *READ FROM ABSOLUTE ADDRESS RABS: Q←MDR, GOTO[QTOAC]; *MAP VIRTUAL ADDRESS [P] BY USING THE "LOADMAP" ROUTINE. IF IT TRAPS, *THE TRAP CAUSE MAY BE ILL. READ, WRITE, OR EXECUTE, BUT THE KIND OF *ACCESS ATTEMPTED WILL SHOW THAT NOTHING WAS ATTEMPTED. IT IS NOT *NECESSARY TO CLEAR THE FORMER MAP ENTRY BEFORE DOING THIS JMC. MVA: P←(REFADR←P) U (1 000000S); *PGRMM LEFADR←P, P←RTEMP, BAMASK[26]; Q←NOT P AND Q, CALL[LOADMAP]; Q←MAP, PQ RCY [0], BAMASK[11]; PQ RCY [33], SAMASK[26], Q←P, GOTO[POQA]; *AC←INSTRUCTION COUNTER. P HAS 10, Q HAS E. E=0 SELECTS LEVEL 1 COUNTER, *E=1 LEVEL 2, ... , E=6 LEVEL 7, AND E=7 NON-INTERRUPT LEVEL COUNTER. *E>7 SELECTS THE "CURRENT" INSTRUCTION COUNTER. RICTR: P-Q, P←@ICTR, GOTO[WICTR,G=1]; P#Q, Q←ICTR, GOTO[QTOAC,ALU<=0]; P←YICTR, GOTO[PTOAC,ALU#0]; LAC←Q, ENDM; *INSTRUCTION COUNTER←AC WICTR: P#Q, Q←LAC, GOTO[.+2,ALU<=0]; GOTO[.+2,ALU#0]; ICTR←Q, RETURN; YICTR←Q, RETURN; *INCREMENT EVENT COUNTER POINTED TO BY Y AND RETURN EVINC: LINT1←P, P←EVCTR, INHINT; Q←P+1, P←Q, INHINT; *WRITE EVENT COUNTER 0-7 IN 16TH WORD OF DISK BLOCKS 0-7 WECTR: Q←P, EVCTR←Q, P←LINT1, INHINT, RETURN; *READ EVENT COUNTER E INTO AC RECTR: P←EVCTR, GOTO[PTOAC]; %UJMC 2 = CSUM16: AC -NWords,,Pointer to block AC+1 Initial checksum Loop performs CSum ← (CSum + Item) LCy 1 over 16-bit items, where the first item is bits 0:15 in the first word and the last item is bits 16:31 in the last word, and sums are ones-complement (wraparound carry) over 16 bits. Carries out of bits 20:35 in the checksum word are folded back after each pair of 16-bit bytes has been processed, so that at the end of each step, the number in AC+1 is .le. 200010b (provided that the original checksum is .le. this value). After the last PDP-10 word has been processed, the carry word is folded one more time to produce a 16-bit final checksum in AC+1. Note that if a zero count is in AC initially, so that the inner loop is not executed, then the checksum in AC+1 will be folded precisely once; this will produce a 16-bit result if the original value is less than 2↑17-1, a 17-bit result if the original value is less than 2↑32-1, and a 22-bit result for arbitrary values. If the inner loop is executed at least once, then the original checksum can be as great as 2↑32-1 and still produce a final result that is .le. 16 bits. This means that after checksumming an odd 16-bit byte at the beginning, one execution of the opcode will produce a 16-bit result, even if the word count is 0, and after checksumming an additional odd byte at the end, one execution of the opcode will produce a 16-bit result. % * P ← LAC, AQ, SAMASK[22], GOTO[CSUM16]; *P/ 16-bits, Q/ previous csum; P ← (P+Q) LCY 1 CS16X: P ← P + Q; PQ LCY [1], Q ← MDR, RETURN; CS16LP: LAC ← P ← P + Q, SAMASK[22], GOTO[PI,H=1]; *P/ 777777, Q/ Pointer to block, AC/ pointer to initial csum. CSUM16: INCAC, GOTO[C16DON,ALU>=0]; MAPVA ← P, CALL[RTOMDR]; P ← MDR, Q ← A0; *P←bits 0:15 of current word, Q←previous csum (.le. 200010b) PQ RCY [24], Q ← LAC, CALL[CS16X]; *Q←previous csum (.le. 1000020b), P←bits 16:31 of current word Q ← P, QQ RCY [4], SAMASK[20], CALL[CS16X]; *P has new checksum (.le. 2400036b); fold it to 17d bits here so that *carries won't propagate outside bits 4:15 of the word. Q ← P, PQ RCY[20], SAMASK[24]; Q ← P, P ← Q, SAMASK[20]; *Largest result from this operation (for Q = 2377777b) is 200010b. LAC ← P + Q, DECAC; P ← LAC, Q ← (2 000002R) RSH 1, SETSF[INTCONDH], GOTO[CS16LP]; *Fold 36-bit result once into the sum of the right-most 16d bits and the *left-most 20d bits (This will result in a 16d-bit result for LAC .le. *377776b, which is the case when the loop has run one or more times.). C16DON: P ← Q ← LAC, SAMASK[20]; QQ RCY [20], Q ← P, SAMASK[24]; LAC ← P + Q, ENDM; %UJMC 3 = BYTBLT: A AC -NWords,,pointer to source block D AC+1 source to destination offset - 1 B AC+2 No. unused bits at right of source C AC+3 Number of bits to right-shift the source word pair so that the right-most word has the destination data right-justified. Approximate equivalent code: SKIPA T1,(A) LP: MOVE T1,T3 ; Collect source word pair in T1..T2 JUMPGE A,EXIT MOVE T2,1(A) MOVE T3,T2 LSH T1,-B ; Squeeze out "crack" between T1 and T2 LSHC T1,-C ; Right-shift T1..T2 so that T2 contains ; the destination data right-justified LSH T2,B MOVEM T2,D+1(A) AOBJN A,LP EXIT: ... % * RTEMP1 ← Q, INCAC, GOTO[BYTB0]; BYTB0: MAPVA ← P ← AQ, SAMASK[22], CALL[RQARG]; *Have P/ AC, Q/ memory data RTEMP ← Q, INCAC; *RTEMP ← 0(AC) P ← RTEMP1, Q ← LAC, INCAC; Q ← LAC, STEMP ← Q, DECAC; *STEMP←B STEMP1 ← Q, P ← P, DECAC, GOTO[BYTBA]; *STEMP1←C *RTEMP/ 0(AC) = first memory word *STEMP1/ right-shift distance for word pair BYTBLP: LAC ← P ← P + Q, INCAC, GOTO[PI,H=1]; *Here the AC register contains its original value + 1 (points at D) *P contains A, which has been put through the ALU. BYTBA: INCAC, GOTO[REMAPPC,ALU>=0]; MAPVA ← P ← P + 1, SAMASK[22], CALL[RTOMDR]; P ← RTEMP, Y ← P; Q ← A0; PQ RCY [Y], Y ← STEMP1; *P←T1 data right-justified P ← MDR, Q ← P; *RTEMP←T2 now to be T1 next time RTEMP ← P, PQ RCY [Y], Q ← LAC, DECAC; Y ← Q, Q ← P ← P, SAMASK[0], CALL[RETN]; *NOTE: delay 1 instruction after Y← before PQ RCY[44-Y] PQ RCY[44-Y]; *LSHIFT by B to zero unused bits MDR ← P, P ← REFADR, Q ← LAC, DECAC; MAPVA ← P ← P + Q, SAMASK[22], CALL[WMDR]; P ← LAC, Q ← (2 000002R) RSH 1, SETSF[INTCONDH], GOTO[BYTBLP]; *Write data in MDR to address in P for which MAPVA has been done *and return to caller. On page fault, PC is not advanced. WMDR: WREF, REFADR ← P, Q ← MDR, GOTO[WMDR2,G=1]; WMDR1: P ← (P) U (BLTWLE), RETURN[G=0]; Q ← WMQ, LEFADR ← P, CALL[LOADMAP]; WREF, Q ← MDR ← WDATA, GOTO[WMDR1,G=0]; WMDR2: P ← (X) U (ACBASE), GOTO[WMDR3,H=0]; MAPVA ← P ← (P) U (BLTWLE); WREFDXK, MDR ← Q, GOTO[WMDR1]; WMDR3: LX ← Q, RETURN; %UJMC 4 = WDUMP0: AC -NWords,,pointer to first src word AC+1 points at destination block Loop moves two 40-bit words from the source to the destination translating into Maxc dump format, where data bytes begin with 0:7 in the first source word and with 0:7 in the first destination word. Translation of nibbles is as follows: Source Destination xx xx xx xx s t xx xx xx xx yy yy yy yy u v -- st yy yy yy yy -- uv where s and u are bits 32:35 in the two source words and t and v are the tag bits in the source words and where -- denotes a garbage byte. In other words, 40-bit words from the source (including 4 tag bits/word) is copied to the destination as 5 8-bit bytes with an extra garbage byte thrown in between the 32nd and 33rd source bits, and the destination is packed 4 8-bit bytes/word. % * P ← LAC, INCAC, GOTO[WDMP0]; WD0LP: GOTO[REMAPPC,ALU>=0]; WDMP0: MAPVA ← P ← P, SAMASK[22], CALL[RTOMDR]; P ← A0, Q ← MDRL, SETSF[INTCONDH]; PQ RCY [4], Q ← MDR, GOTO[PI,H=1]; *P/ t0 00 00 00 0 PQ RCY [14], Q ← LAC, DECAC; *P/ -- st 00 00 0 RTEMP ← P, P ← Q, SAMASK[22]; *RTEMP/ -- st 00 00 0 MAPVA ← P, CALL[WMDR]; *Write xx xx xx xx - P ← LAC, INCAC; MAPVA ← P ← P+1, SAMASK[22], CALL[RTOMDR]; Q ← A0, P ← STEMP ← MDR; PQ RCY [20], Q ← RTEMP, STEMP1 ← MDRL; MDR ← P OR Q, P ← LAC; MAPVA ← P ← P+1, SAMASK[22], CALL[WMDR]; P ← A0, Q ← STEMP; PQ RCY [24], Q ← STEMP1; *P/ yy yy u0 00 0 RTEMP ← P, 0Q RCY [4], Q ← STEMP; *P/ v0 00 00 00 0 PQ RCY [34], SAMASK[14], Q ← RTEMP; *P/ 00 00 00 uv 0 MDR ← P OR Q, Q ← LAC, P ← 2 000002R; MAPVA ← P ← P+Q, SAMASK[22], CALL[WMDR]; Q ← LAC, P ← 2 000002R; P ← P+Q, Q ← (2 000002R) RSH 1; LAC ← P+Q, DECAC; P ← LAC, Q ← 2 000002R; LAC ← P ← P+Q, INCAC, GOTO[WD0LP]; %UJMC 5 = WDUMP1: AC -NWords,,pointer to first src word AC+1 Right-justified 8-bit byte from the previous iteration. AC+2 address of destination block Like WDUMP0 but with a different destination alignment. Translation of nibbles is as follows: Source Destination xx xx xx xx s t ll xx xx xx yy yy yy yy u v xx -- st yy yy yy yy -- where ll is the byte from the previous iteration and where uv is left right-justified in AC+1 for the next iteration. % * P ← LAC, INCAC, GOTO[WDMP1]; WD1LP: GOTO[REMAPPC,ALU>=0]; WDMP1: MAPVA ← P ← P, SAMASK[22], CALL[RTOMDR]; P ← STEMP ← MDR, Q ← LAC, INCAC; RTEMP ← P, PQ RCY [10], Q ← MDRL, SETSF[INTCONDH]; MDR ← P, 0Q RCY [4], Q ← RTEMP, GOTO[PI,H=1]; PQ RCY [10]; *P/ -s t0 00 00 0 PQ RCY [14], Q ← LAC, DECAC; *P/ xx -- st 00 0 RTEMP ← P, P ← Q, DECAC; MAPVA ← P ← P, SAMASK[22], CALL[WMDR]; P ← LAC, INCAC; MAPVA ← P ← P+1, SAMASK[22], CALL[RTOMDR]; P ← STEMP ← MDR, Q ← A0, INCAC; PQ RCY [30], Q ← RTEMP, STEMP1 ← MDRL; MDR ← P OR Q, P ← LAC; MAPVA ← P ← P+1, SAMASK[22], CALL[WMDR]; P ← A0, Q ← STEMP; PQ RCY [34]; MDR ← P, P ← LAC, Q ← 2 000002R; MAPVA ← P ← P+Q, SAMASK[22], CALL[WMDR]; *Now update AC's for the iteration P ← LAC, Q ← 2 000002R; P ← P+Q, Q ← (2 000002R) RSH 1; LAC ← P+Q, DECAC; *DEST AC ← DEST AC+3 P ← A0, Q ← STEMP1; PQ RCY [4], Q ← STEMP; PQ RCY [40], SAMASK[10]; LAC ← P, DECAC; *Byte carried to next iteration P ← LAC, Q ← 2 000002R; LAC ← P ← P+Q, INCAC, GOTO[WD1LP]; *Source AC %JMC, A CATCH-ALL INSTRUCTION ADDED TO THE PDP-10, IS PRIVILEGED. E[22,30] SELECTS ONE OF 128 MICROCODED ROUTINES FOR EXECUTION. THE TABLE OF MICROINSTRUCTIONS BEGINNING AT "ALEVX" IS USED TO DISPATCH TO THE SELECTED ROUTINE WITH E[31,43] IN P AND AC IN Q. I = 6 + NUJMCS + NJMCS + 72 = 116 (+8 COMMENTED OUT) % *MUST USE REFADR JMC: REFADR←P, PQ RCY [13], Q←NPC, RETURN, SETSF[UM&J], BAMASK[7]; *JMC DISPATCH. HERE WITH -1 IN RTEMP AND LTEMP, E[30,43] IN P, AC IN Q ALEVX: X←P, PQ RCY [6], SAMASK[3], GOTO[ASNLEV]; *0 PILEV P[33,35] TO DEVICE P[36,43] Q←44S, RTEMP←Q, GOTO[ASNLOC]; *1 ASSIGN 24-BIT PARAM. TO DEV IN P Q←44S, RTEMP←Q, GOTO[ALEVLOC]; *2 ASSIGN BOTH LEV AND PARAM YKPTR←P, GOTO[WECTR]; *3 WRITE EVENT COUNTER E X←P, SETSF[G], GOTO[IOCK]; *4 CLEAR INTERRUPT REQUEST FOR DEV P X←P, SETF[G], GOTO[IOCK]; *5 INITIATE INTERRUPT REQUEST FOR DEV P RPGRT3←Q, PQ RCY [0], SAMASK[3], GOTO[SPILEV]; *6 SET PI LEVEL *FOR DEVICES SELECTED BY AC P←FINTS, GOTO[READIR]; *7 AC←INTERRUPTING DEVICE MASK P←FINTS, BRKP[1], GOTO[ILLIO]; *10 INITIATE INTS FOR DEVICES IN AC MASK CLEARF[PIACTIVE&G], GOTO[CONINTCOND]; *11 TURN OFF PI SYSTEM SETF[PIACTIVE&MICRO], GOTO[CONINTCOND]; *12 TURN ON PI SYSTEM SETF[INCMP&K], RETURN; *13 ENTER INCOMPATIBLE MODE CLEARF[INCMP&K], RETURN; *14 LEAVE INCOMPATIBLE MODE X←P, SETSF[G], GOTO[SIGNAL]; *15 SIGNAL NOVA DEVICE E (BIT 43-E) PRESC: P←GOTAB, IRET, INHINT, GOTO[PRES]; *16 PROCESSOR RESET P←777777R, AMASK[17], SETSF[INCMP&K], GOTO[PIREAD]; *17 READ PI STATE Q←SLOCLOW, GOTO[SETSYSP]; *20 SET SYSTEM PARAMETER TO AC MAPRESET: CLEARF[CUM&G], Y←NULL, GOTO[MAPRES]; *21 TURNOFF MAPPING P←Y←NULL, GOTO[SETPLO], Q←P; *22 SET PLO EQUAL TO E READ←PSWITCH, GOTO[ASWIT]; *23 RELOAD BASE REGS. WITHOUT MAP CLEAR Q←1000S, GOTO[VPGCLR]; *24 CLEAR VIRTUAL PAGE E CLEARF[CUM&G], Y←A1, GOTO[MAPCLR]; *25 CLEAR ABSOLUTE PAGE E GOTO[USWIT], P←Y←PLO; *26 SWITCH MAP TO NEW PROCESS YKPTR←KUNIT←P, GOTO[KOFF]; *27 DESELECT DISK UNIT E YKPTR←KUNIT←P, GOTO[KON]; *30 SELECT DISK UNIT E WITH THE *MAXIMUM DISK ADDRESS IN AC P←377 000000S, GOTO[KNOPDP]; *31 DISABLE PDP-10 SECTOR INTERRUPTS *FOR THE PACK IN AC P←377 000000S, GOTO[KSEEK]; *32 ENABLE PDP-10 SECTOR INTERRUPTS *AND SEEK IF ARM # CURRENT POSITION READ←DLSBS, GOTO[RESIO]; *33 I/O RESET MAPVA←P←AQ, SAMASK[22], GOTO[KGO]; *34 DO DATA TRANSFER SPECIFIED *BY COMMAND POINTED TO BY V.A. IN AC WRITE←P, INHINT, GOTO[WABS]; *35 MOVEM AC,E[31,43] ABSOLUTE READ←P, GOTO[RABS]; *36 MOVE AC,E[31,43] ABSOLUTE MAPVA←P←AQ, SAMASK[22], GOTO[MVA]; *37 MAP VIRTUAL TO ABSOLUTE *ADDRESS (1240,,E + 100000,,0 FOR READ *40400,,0 FOR WRITE AND 20000 FOR XCT) SETF[G], GOTO[RICT1]; *40 WRITE INST. COUNTER E Q←LAC, GOTO[CHECK]; *41 CHECK MICROMEMORY (MUST HAVE 0 *IN AC AT CALL. CLOBBERS AC TO AC+4) Q←P, P←NULL, SETF[J], GOTO[LEVX]; *42 TURN OFF PI LEVELS Q←P, P←NULL, SETF[MICRO], GOTO[LEVX]; *43 TURN ON PI LEVELS SETF[LOGF&K], RETURN; *44 ENABLE OPTIONAL MAIN LOOP PATH CLEARF[LOGF&K], RETURN; *45 DISABLE OPTIONAL MAIN LOOP PATH DM[DLC,777]; DLC[E1[JMC] E2[JMC1] E3[ADD[4000,IP[ILC],NOT[IP[JMC]]]]]; JMC1: MDR←P+Q, SETSF[G], GOTO[ILLIO,J=1]; Q←STACK, LTEMP←RTEMP←A1; P-Q, NPC←MDR; GOTO[ILLIO,ALU>=0], P←REFADR, Q←LAC, AMASK[13], POP; UJMC: REFADR←P, PQ RCY [13], Q←NPC, BAMASK[7], SETSF[J], RETURN; RICT1: P←10L, Q←YKPTR←P, GOTO[RICTR]; *0 READ INST. COUNTER E YKPTR←P, GOTO[RECTR]; *1 AC←EVENT COUNTER E P ← LAC, AQ, SAMASK[22], GOTO[CSUM16]; *2 CSUM16 RTEMP1 ← Q, INCAC, GOTO[BYTB0]; *3 BYTBLT P ← LAC, INCAC, GOTO[WDMP0]; *4 WDUMP0 P ← LAC, INCAC, GOTO[WDMP1]; *5 WDUMP1 DM[DLC,776]; DLC[E1[UJMC] E2[JMC1] E3[ADD[4000,IP[ILC],NOT[IP[UJMC]]]]];