Google
 

Trailing-Edge - PDP-10 Archives - tops10_tools_bb-fp64b-sb - 10,7/frecor/frecor.mac
There are 5 other files named frecor.mac in the archive. Click here to see a list.
	TITLE	FRECOR  --  Program to figure out where all the Free Core went
	SUBTTL	C.D.O'Toole/CDO   18-Mar-87


;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.

;COPYRIGHT (C) 1979,1980 BY DIGITAL EQUIPMENT CORPORATION


	SEARCH	MACTEN, UUOSYM
	SALL


;VERSION STUFF

	FCREDT==4		;EDIT NUMBER
	FCRVER==704		;MAJOR VERSION
	FCRMIN==0		;MINOR VERSION
	FCRWHO==0		;WHO LAST EDITTED

	LOC	137
	VRSN.	FCR
	RELOC

;CHANNELS

	XPN==0			;FOR READING CRASHES

;AC DEFINITIONS

	F==0			;A FLAG REG
		FL.EOL==1B0	;END OF LINE SEEN
		FL.ETX==1B1	;END OF PHYSICAL LINE SEEN
		FL.RSC==1B2	;HAVE GETONE USE RESCAN LAST CHARACTER
		FL.UPZ==1B3	;^Z TYPED, EXIT AFTER COMMAND

	T1==1			;TEMPORARY ACS FOR ANY SUBROUTINE
	T2==2
	T3==3
	T4==4
	T5==5

	CH==6			;CHARACTER HOLDER

	UU==7			;FOR LUUO HANDLER
	UA==10			;HOLDS LUUO EFFECTIVE ADDRESS

	J==11			;HOLDS JOB NUMBER FOR LOOPS

	P1==12			;PRESERVED ACS FOR ANY COMMAND PROCESSOR
	P2==13
	P3==14
	P4==15
	P5==16

	P==17


	.PSECT	CODE,740000	;START CODE PSECT AT FYSORG
	SUBTTL	Macros and other stuff

	DEFINE	FORMAT(A),<
		..N==0
		IRP A,<
			IFN ..N,<XLIST>
			IFE ..N&1,<IFNB <A>,<TEXT.(A)>>
			IFN ..N&1,<A>
			..N==..N+1
		>
		LIST
		SALL
	>

	DEFINE	TEXT.(A),<OUTSTR[ASCIZ\A\]>

	DEFINE	GTTAB(ENTRY),<
		MOVE	T1,[ENTRY]
		XLIST
		PUSHJ	P,GTBSPY
		  HALT	.
		LIST
		SALL
	>

	OPDEF	DEC	[001000,,0]	;OUTPUT DECIMAL NUMBER
	OPDEF	OCT	[002000,,0]	;OUTPUT OCTAL NUMBER
	OPDEF	SIX	[003000,,0]	;OUTPUT SIXBIT VALUE
	OPDEF	PER	[004000,,0]	;OUTPUT FRECOR NUMBERS AS PERCENT
	OPDEF	CRLF	[005000,,0]	;DO A CRLF
	OPDEF	OCT4	[006000,,0]	;OUTPUT OCTAL * 4
	OPDEF	GTTO	[007000,,0]	;GETTAB VALUE IN OCTAL
	OPDEF	GTTD	[010000,,0]	;GETTAB VALUE IN DECIMAL
	OPDEF	GTTA	[011000,,0]	;GETTAB VALUE AS ASCII WORD
	OPDEF	GTTD2	[012000,,0]	;GETTAB VALUE, DECIMAL, 2 DIGITS
	DEFINE	MSYM(NAME,VALUE),<NAME==VALUE>

	MSYM	MONITR,0	;SYMBOLIZE LOCATION 0 OF THE MONITOR
	MSYM	NUMTAB,410	;WHERE .GTSLF LIVES
	MSYM	DEVNAM,0	;SIXBIT DEVICE NAME IN DDB
	MSYM	DEVSER,3	;LINK TO NEXT DDB
	MSYM	DEVMOD,4	;DEVICE MODE WORD
	MSYM	DEVXTR,13	;POINTER TO CDT IF A MPX DDB
	MSYM	STRNAM,0	;NAME OF STRUCTURE
	MSYM	STRSYS,1	;LH LINK TO NEXT STRUCTURE
	MSYM	STRUNI,2	;LH LINKS TO FIRST UNIT IN STRUCTURE
	MSYM	UNINAM,0	;NAME OF UNIT
	MSYM	UNISTR,16	;CONTINUE UNITS IN STRUCTURE
	MSYM	UNISPU,62	;SPT SIZE IN THIS WORD
	MSYM	UNIWPS,62	;SAT SIZE IN IT TOO
	MSYM	UNISAB,65	;LINK TO SAB RING
	MSYM	UNISPT,112	;LINK TO SPT
	MSYM	SABRNG,0	;LINK TO NEXT SAB IN RING
	MSYM	PTRSYS,0	;LINK TO NEXT PTR COPY BLOCK
	MSYM	.LBNHS,0	;POINTER TO NEXT ENQ/DEQ LOCK BLOCK
	MSYM	.LBLEN,1	;L.H. = LENGTH OF THIS LOCK BLOCK
	MSYM	.LBNQ,2		;POINTER TO FIRST ENQ/DEQ QUEUE BLOCK
	MSYM	.LBNMS,7	;L.H. = LENGTH OF MASK BLOCK
	MSYM	.QBNQ,2		;POINTER TO NEXT ENQ/DEQ QUEUE BLOCK
	MSYM	.QBMSK,6	;POINTER TO MASK BLOCK FOR THIS Q-BLOCK
	MSYM	.CBNHB,0	;POINTER TO NEXT CACHE BLOCK
	MSYM	.CBNAB,2	;POINTER TO NEXT ACTIVE CACHE BLOCK
	MSYM	.CBDAT,6	;ADDRESS OF CACHED BLOCK
	MSYM	.CBLEN,10	;LENGTH OF A CACHE BLOCK
	MSYM	.CTNXT,2	;POINTER TO NEXT CONTEXT BLOCK
	MSYM	.CTBPR,43	;BEGINNING OF PARAMETER AREA
	MSYM	.CXSCX,2	;POINTER TO SAVED CONTEXT
	MSYM	.CXPIA,43	;POINTER TO SAVED JBTPIA
	MSYM	.CTSIZ,200	;SIZE OF A CONTEXT BLOCK
	MSYM	AHBNXT,0	;POINTER TO NEXT ALLOCATION HEADER BLOCK
	MSYM	AHBAEB,14	;ALLOCATION HEADER EXTENT BLOCK POINTER
	MSYM	AEBNXT,0	;POINTER TO NEXT EXTENT BLOCK
	MSYM	AEBBMP,5	;BITMAP TO EXTENT
	MSYM	ETDOBK,51	;DTE OUTPUT BUFFER
	MSYM	ETDIBK,52	;DTE INPUT BUFFER
	MSYM	UBLSIZ,223	;SIZE OF DTE BUFFER MINUS HEADER
	MSYM	MS.MEM,<3,,0>	;SECTION FOR PAGTAB/MEMTAB

;SYMBOLS NOT GETTAB'ABLE

	PDBLEN==111		;WORDS IN A PDB
	DSKDDS==66		;WORDS IN A DISK DDB
	MPXLEN==32		;WORDS IN A MPX DDB
	SPROTO==41		;WORDS IN A MAG TAPE LABEL DDB
	STRLEN==27		;WORDS IN STR DATA BLOCK
	SPTFIR==0		;SPT OVERHEAD
	SABBIT==5		;SAB OVERHEAD
	LNMLEN==4		;WORDS IN A LOGICAL NAME TABLE
	PTHLEN==5+2		;WORDS IN A PATH BLOCK
	PTRCOR==3*4		;WORDS IN A UPDATE FILE POINTER COPY BLOCK
	NWSCTX==30		;WORDS IN A SAVED CONTEXT BLOCK
	.PDSCX==37		;WORD IN PDB THAT POINTS TO CONTEXT BLOCK
	.PDSAC==76		;FIRST CONTEXT
	.PDCTC==77		;CURRENT CONTEXT
	DVDSK==200000		;BIT IN DEVMOD FOR DSK DEVICE
	SHRSEG==200000		;BIT IN JBTSTS FOR A SEGMENT SAYING SHARABLE
	QBSIZE==7		;SIZE OF ENQ/DEQ QUEUE BLOCK
;PAGTAB DEFINITIONS

	PAGTAB==730000		;WHERE IT LIVES (ON KS'S ANYWAY)
		PT.FRE==400000	;ON THE FREE LIST
		PT.LPH==200000	;LOCKED PHYSICALLY CONTIGUOUS
		PT.LEV==100000	;LOCKED IN EVM
		PT.LIP==040000	;LOCKED IN PLACE
		PT.NXM==020000	;NON-EXISTANT
		PT.MON==010000	;BELONGS TO THE MONITOR
		PT.IPC==004000	;BELONGS TO IPCF
		PT.TNC==002000	;TEMPORARILY UNCACHED (1099 ONLY)

;THINGS THAT CAN'T REALLY CHANGE, JUST MADE SYMBOLIC

	DSKBLK==200		;SIZE OF A DISK BLOCK
	NBCSHE==20		;NUMBER OF DISK BLOCKS TO CACHE FOR "READ" COMMAND

;STORAGE

OPNBLK:	EXP	17,0,0		;DUMP MODE, STR FILLED IN, NO BUFFERS
LUKBLK:	BLOCK	4		;LOOKUP BLOCK
EXEDIR:	BLOCK	DSKBLK		;EXE DIRECTORY
DCACHD:	BLOCK	NBCSHE*DSKBLK	;SPACE FOR THE CACHE
DCACHE:	BLOCK	NBCSHE		;SPACE FOR CACHE POINTERS

PDL:	BLOCK	50		;A STACK
SAVCHR:	BLOCK	1		;SAVED CHARACTER FROM GETONE
LOCORE:	BLOCK	1		;COPY OF MONITOR "LOCORE"
FRUSED:	BLOCK	1		;COPY OF "FRUSED"
FREPTR:	BLOCK	1		;COPY OF "FREPTR"
RNGTAB:	BLOCK	1		;ADDRESS OF RANGE TABLE
PDBPTR:	BLOCK	1		;ADDRESS OF JBTPDB FOR NULL JOB
JBTMXL:	BLOCK	1		;HIGHEST JOB+SEGN
JOBMAX:	BLOCK	1		;NUMBER OF JOBS (0-N)
FREAVB:	BLOCK	1		;NUMBER OF CHUNKS POSSIBLE
FRERTN:	BLOCK	1		;NUMBER OF CHUNKS RETURNED
PGTLEN:	BLOCK	1		;NUMBER OF PAGES DESCRIBED BY PAGTAB
EPTADR:	BLOCK	1		;BOOT CPU'S EPT
EPMADR:	BLOCK	1		;BOOT CPU'S EXEC MAP
JBTUPM:	BLOCK	1		;WHERE JBTUPM IS
JBTAD2:	BLOCK	1		;WHERE JBTAD2 IS
JBTADR:	BLOCK	1		;WHERE JBTADR IS
JBTSTS:	BLOCK	1		;WHERE JBTSTS IS
FYSORG:	EXP	740000		;ORIGIN OF PER-PROCESS AREA
LOWLIM:	EXP	CODE-400K	;LIMIT FOR PEEKING
PITSIZ:	BLOCK	1		;SIZE OF JBTPIA ENTRY
PTBADR:	BLOCK	1		;ADDRESS OF PAGTAB ON THIS SYSTEM
ERPTSZ:	BLOCK	1		;SIZE OF DAEMON ERROR ENTRY
ESVIDX:	BLOCK	1		;START OF ERROR TABLE
ERPTMX:	BLOCK	1		;MAXIM
EPKIDX:	BLOCK	1		;INDEX INTO TABLE
ERPTBK:	BLOCK	10		;THE BLOCK
	SUBTTL	Entry Point and Main Command Dispatch

FRECOR:	JFCL			;NO CCL ENTRY
	RESET			;START FRESH
	MOVE	P,[IOWD 50,PDL]	;GET A STACK
	MOVE	T1,[PUSHJ P,UUOCON] ;HOW TO GET TO THE LUUO HANDLER
	MOVEM	T1,41		;STORE IN JOBDAT
	MOVEI	T1,CODE-1-400000 ;HIGHEST ADDRESS WHERE I'LL PUT MONITOR DATA
	CORE	T1,		;ASK FOR IT ALL
	  HALT	.		;WHAT

NXTCOM:	OUTSTR	[ASCIZ/FRECOR>/] ;PROMPT THE OPERATOR
	SETZB	F,SAVCHR	;CLEAR FLAGS, NO SAVED CHARACTER NOW
	PUSHJ	P,GETSIX	;GET COMMAND AND MASK
	JUMPE	T1,NULCMD	;NULL COMMAND
	MOVE	T3,[-NUMCMD,,CMDTBL] ;GET AOBJN TO COMMAND TABLE
	PUSHJ	P,TABSRC	;LOOK IT UP IN THE TABLE
	  SKIPA T2,[NUMCMD]	;ILLEGAL COMMAND
	  MOVEI	T2,NUMCMD+1	;AMBIGUOUS COMMAND
	PUSHJ	P,@CMDDSP(T2)	;EXECUTE IT
MAIN.1:	PUSHJ	P,FLUSH		;EAT UP REST OF INPUT LINE
	TLNN	F,(FL.UPZ)	;YES, WAS END A CONTROL-Z
	JRST	NXTCOM		;NO, GET ANOTHER COMMAND
	MONRT.			;YES, EXIT NOW
	JRST	FRECOR		;RESTART PROGRAM ON CONTINUE
NULCMD:	TLNN	F,(FL.EOL)	;JUST AN EMPTY LINE
	PUSHJ	P,BADFMT	;NO, COMPLAIN
	JRST	MAIN.1		;THEN FLUSH INPUT LINE

	DEFINE	COMNDS,<
	XLIST
		X	DDT,<go to DDT>
		X	FIND,<information about monitor pages>
		X	HELP,<types out this text>
		X	MONITOR,<look at the running monitor>
		X	READ,<FILE-SPEC Read a crash file>
	LIST
	SALL
	>

	DEFINE	X(CMD,STR),<<SIXBIT/CMD     />>
CMDTBL:	COMNDS			;GENERATE THE COMMAND TABLE
NUMCMD==<.-CMDTBL>		;NUMBER OF COMMANDS

	DEFINE	X(CMD,STR),<EXP %'CMD>
CMDDSP:	COMNDS			;GENERATE THE DISPATCH TABLE
	EXP	ILLCMD		;TYPE OUT ILLEGAL COMMAND
	EXP	AMBIGC		;TYPE OUT AMBIGUOUS COMMAND

	DEFINE	X(CMD,STR),<EXP [ASCIZ\STR\]>
CMDHLP:	COMNDS			;GENERATE THE HELP DESCRIPTORS
	SUBTTL	Random Error Message Printers for Command Scanner

BADEXE:	OUTSTR	[ASCIZ/?Bad EXE Header code - Not an EXE file/]
	JRST	ERRXIT		;END LINE AND RETURN
COMEXE:	OUTSTR	[ASCIZ/?EXE Directory is too complex/]
	JRST	ERRXIT		;END LINE AND RETURN
AMBIGA:	OUTSTR	[ASCIZ/?Ambiguous Argument - "/]
	JRST	ILSXIT		;FINISH ERROR MESSAGE
ILLARG:	OUTSTR	[ASCIZ/?Unknown Argument - "/]
	JRST	ILSXIT		;FINISH ERROR MESSAGE
NOARGS:	TLNN	F,(FL.EOL)	;END OF INPUT
	JRST	BADFMT		;NO, GIVE DIFFERENT ERROR
	OUTSTR	[ASCIZ/?Missing Argument/]
	JRST	ERRXIT		;END LINE AND RETURN
JUNK:	OUTSTR	[ASCIZ/?Junk after end of command - "/]
	SKIPA			;OUTPUT OFFENDING CHARACTER
BADFMT:	OUTSTR	[ASCIZ/?Command Error - "/]
	CAIGE	CH,40		;A REGULAR CHARACTER
	JRST	[OUTCHR ["^"]	;NO, OUTPUT UP-ARROW
		ADDI CH,100	;MAKE A REAL LETTER
		JRST .+1]	;RETURN INLINE
	OUTCHR	CH		;OUTPUT OFFENDING CHARACTER
	JRST	ILLXIT		;FINISH UP AND RETURN
AMBIGC:	OUTSTR	[ASCIZ/?Ambiguous Command - "/]
	SKIPA			;SKIP OVER OTHER MESSAGE
ILLCMD:	OUTSTR	[ASCIZ/?Unknown Command - "/]
ILSXIT:	PUSHJ	P,SIXOUT	;APPEND COMMAND TYPED
ILLXIT:	OUTCHR	[""""]		;CLOSE QUOTES
ERRXIT:
CRPOPJ:	OUTSTR	[BYTE (7)15,12,0]
	POPJ	P,
	SUBTTL	The "FIND" Command

%FIND:	SKIPN	PGTLEN		;DO WE KNOW ABOUT PAGTAB YET
	JRST	[OUTSTR[ASCIZ/?Use READ or MONITOR command first/]
		 JRST ERRXIT]	;END LINE AND RETURN
	PUSHJ	P,GETNUO	;GET OCTAL PAGE NUMBER
	SKIPGE	P2,T1		;COPY INTO P2 FOR LATER USE
	JRST	NOARGS		;IF -1, BAD ARGUMENTS (OR NONE)
	MOVE	P1,T1		;COPY NUMBER
	PUSHJ	P,CMDEND	;NO MORE ARGUMENTS
	  JRST	JUNK		;ISN'T
	PUSHJ	P,PGFTCH	;FETCH THE PAGTAB ENTRY FOR IT
	TLNE	T1,PT.FRE	;A FREE PAGE
	JRST	[OUTSTR[ASCIZ/Page is on the Free List/]
		 JRST CRPOPJ]	;END LINE AND RETURN
	TLNE	T1,PT.NXM	;NON-EXISTANT
	JRST	[OUTSTR[ASCIZ/Page is off-line/]
		 JRST CRPOPJ]	;END LINE AND RETURN
	TLNE	T1,PT.MON	;BELONG TO THE MONITOR
	JRST	[OUTSTR[ASCIZ/Page belongs to the Monitor/]
		 JRST CRPOPJ]	;END LINE AND RETURN
	TLNE	T1,PT.IPC	;BELONG TO IPCF
	JRST	[OUTSTR[ASCIZ/Page in somebody's IPCF queue/]
		 JRST CRPOPJ]	;END LINE AND RETURN
	TLNE	T1,PT.LPH!PT.LEV!PT.LIP ;ANY LOCK BITS
	OUTSTR	[ASCIZ/Page is locked /]
	TLNE	T1,PT.LPH	;PHYSICALLY CONTIGUOUS
	OUTSTR	[ASCIZ/physically contiguously/]
	TLNE	T1,PT.LEV	;IN EVM
	OUTSTR	[ASCIZ/in EVM/]
	TLNE	T1,PT.LIP	;IN PLACE
	OUTSTR	[ASCIZ/in place/]
	TLNE	T1,PT.LPH!PT.LEV!PT.LIP ;ANY OF THE ABOVE
	OUTSTR	[ASCIZ/ for /]
	MOVE	J,JOBMAX	;START AT HIGHEST JOB NUMBER
FIND.1:	HRRZ	T1,@JBTUPM	;PAGE NUMBER OF UPMP
	CAIN	T1,(P2)		;THIS THE ONE WE'RE LOOKING FOR
	JRST	[OUTSTR[ASCIZ/UPMP of /]
		 JRST FIND.5]	;PRETTY UP OUTPUT AND DONE
	SOJG	J,FIND.1	;LOOK AT ALL UPMP'S
	MOVEI	J,1		;START LOOKING AT ALL JOBS/SEGMENTS
FIND.2:	MOVSI	T1,SHRSEG	;SHARABLE SEGMENT BIT
	CAMLE	J,JOBMAX	;IS THIS A SEGMENT
	TDNE	T1,@JBTSTS	;YES, IS IT SHARABLE
	SKIPN	@JBTADR		;CHECK IF IN CORE
	JRST	FIND.4		;NON-SHARABLE SEGMENTS ARE COUNTED IN JOB LOW SEG
	LDB	P1,[POINT 13,@JBTUPM,35] ;JBYHSA
	CAMG	J,JOBMAX	;IS THIS A HIGH SEGMENT
	LDB	P1,[POINT 13,@JBTAD2,35] ;JBYLSA
FIND.3:	CAIN	P1,(P2)		;IS THIS THE PAGE WE'RE LOOKING FOR
	JRST	FIND.5		;FOUND
	PUSHJ	P,PGFTCH	;GET PAGTAB ENTRY FOR PAGE IN JOB/SEGMENT
	HRRZ	P1,T1		;GET LINK TO NEXT PAGE IN SEGMENT/JOB
	JUMPN	P1,FIND.3	;CONTINUE WITH JOB/SEGMENT
FIND.4:	CAMG	J,JBTMXL	;OFF THE END OF JOBS/SEGMENTS
	AOJA	J,FIND.2	;NO, LOOK AT NEXT ONE
	OUTSTR	[ASCIZ/?Not found for any job or segment/]
	JRST	CRPOPJ		;END LINE AND RETURN
FIND.5:	CAMLE	J,JOBMAX	;JOB OR SEGMENT
	SKIPA	T1,[[ASCIZ/Segment /]]
	MOVEI	T1,[ASCIZ/Job /]
	FORMAT	<,<OUTSTR @T1>,,<DEC J>,< (>,<OCT J>,< octal)>>
	JRST	CRPOPJ		;END LINE AND RETURN
	POPJ	P,
	SUBTTL	The "READ" Command

%READ:	PUSHJ	P,GETFN		;GO GET THE FILE TO READ
	  POPJ	P,		;ALREADY GAVE ERROR
	PUSHJ	P,CMDEND	;REALLY OUGHT TO BE THE END
	  JRST	JUNK		;ISN'T
	OPEN	XPN,OPNBLK	;OPEN THE STR
	  POPJ	P,		;FAILED
	LOOKUP	XPN,LUKBLK	;GET THE FILE
	  POPJ	P,		;FAILED
	IN	XPN,IOLST1	;READ EXE DIRECTORY, PAGE 0 INTO 1000
	 CAIA			;OK SO FAR
	  HALT	.		;WHAT
	MOVE	T1,[1140,,140]	;140 FROM EXE FILE INTO MY 140
	BLT	T1,777		;GET ALL OF PAGE 0 BUT JOBDAT
	IN	XPN,IOLST2	;GET REST OF FILE LOW SEGMENT
	 CAIA			;OK SO FAR
	  HALT	.		;WHAT
	HLRZ	T1,EXEDIR	;GET EXE HEADER CODE
	CAIE	T1,1776		;BETTER BE
	JRST	BADEXE		;BAD DIRECTORY FORMAT
	HRRZ	T1,EXEDIR	;GET LENGTH OF DIRECTORY
	CAIL	T1,DSKBLK	;CHECK AGAINST SPACE ALLOCATED
	JRST	COMEXE		;TOO COMPLEX
	MOVEI	T1,DCACHD	;POINT TO THE DATA BUFFERS
	MOVSI	T2,-NBCSHE	;NUMBER OF BUFFERS
	HRROM	T1,DCACHE(T2)	;MARK ENTRY AVAILABLE
	ADDI	T1,DSKBLK	;STEP TO NEXT BUFFER
	AOBJN	T2,.-2		;PRIME THE TABLES
	JRST	MONCOM		;JOIN COMMON CODE

IOLST1:	IOWD	1000,EXEDIR	;EXE DIRECTORY (CLOBBER SOME OF DCACHD)
	IOWD	1000,1000	;PAGE 0 INTO PAGE 1
	0
IOLST2:	IOWD	CODE-401K,1000	;ENTIRE LOW SEGMENT NOW
	0
	SUBTTL	The "MONITOR" Command

%MONIT:	PUSHJ	P,CMDEND	;NO ARGUMENTS
	  JRST	JUNK		;JUNK ON THE LINE
	SETZM	EXEDIR		;NO EXE DIRECTORY NOW
	MOVE	T1,[%CNSIZ]	;SIZE OF THE MONITOR
	GETTAB	T1,		;DON'T USE SIMULATOR, WANT REAL CURRENT
	  HALT	.		;WHAT
	MOVEI	T1,-1(T1)	;WANT HIGHEST ADDRESS
	CAILE	T1,377777	;LESS THAN 128K?
	MOVEI	T1,377777	;NO, GO FOR THE MAX
	CAILE	T1,CODE-400000	;TOO BIG?
	MOVEI	T1,CODE-400000	;YEP
	MOVE	T2,T1		;SAVE ADDRESS
	SPY	T1,		;SPY ON THE MONITOR
	  HALT	.		;WHAT
	MOVE	T1,[400140,,140] ;MONITOR 140 TO MY 140
	BLT	T1,(T2)		;COPY SO WE DON'T GET CONFUSED BY CHANGES
	HRRZM	T1,LOWLIM	;SAVE INITIAL LIMIT
	JRST	MONCOM		;JOIN COMMON CODE
	SUBTTL	Check Out the Free Core

MONCOM:	FORMAT	<,<CRLF>,<Monitor is:>,<CRLF>,,<CRLF>,,<GTTA [%CNFG0]>>
	FORMAT	<,<GTTA [%CNFG1]>,,<GTTA [%CNFG2]>,,<GTTA [%CNFG3]>,,<GTTA [%CNFG4]>>
	OUTCHR	[11]		;ALIGN WITH A TAB
	GTTAB	%CNMON		;GET MONTH NUMBER
	OUTSTR	MONTAB-1(T1)	;OUTPUT MONTH
	FORMAT	<< >,<GTTD [%CNDAY]>,<,>,<GTTD [%CNYER]>>
	FORMAT	<< >,<GTTD [%CNHOR]>,<:>,<GTTD2 [%CNMIN]>,<:>,<GTTD2 [%CNSEC]>>
	FORMAT	<,<CRLF>,,<CRLF>>
	GTTAB	%CNNWC		;AMOUNT OF CORE POSSIBLE
	LSH	T1,-^D9		;TO NUMBER OF PAGES
	MOVEM	T1,PGTLEN	;STORE LENGTH OF PAGTAB
	GTTAB	%CNBCP		;FIND A BOOT CPU
	LSH	T1,1		;*2 FOR CPU SPECIFIC GETTABS
	MOVE	P1,T1		;SAVE IT
	ADD	T1,[%CCTOS]	;FIND EPT ADDRESS
	PUSHJ	P,GTBSPY	;GET IT (SHOULD SMARTEN UP GTTAB MACRO)
	  HALT	.		;WHAT?
	MOVEM	T1,EPTADR	;SAVE FOR LATER
	ADDI	T1,1000		;OFFSET TO EXEC MAP
	MOVEM	T1,EPMADR	;SAVE FOR LATER
	MOVE	T1,[%CCTYP]	;FIND CPU TYPE
	ADD	T1,P1
	PUSHJ	P,GTBSPY	;GET IT
	  HALT	.		;WHAT?
	CAIE	T1,.CCKLX	;KL-10 SYSTEM?
	SKIPA	T1,[PAGTAB]	;NO, GET KS PAGTAB OFFSET
	MOVSI	T1,(MS.MEM)	;YES, GET PAGTAB/MEMTAB SECTION
	MOVEM	T1,PTBADR	;WHERE PAGTAB STARTS ON THIS MACHINE
	GTTAB	%VMPPB		;GET BEGINNING OF PER-PROCESS AREA
	MOVEM	T1,FYSORG	;SAVE IT
	CAILE	T1,CODE-400K	;DOES IT FIT?
	MOVEI	T1,CODE-400K	;NO, STOP AT OUR LIMIT
	CAMG	T1,LOWLIM	;IF THIS IS A RESTRICTION,
	MOVEM	T1,LOWLIM	;SAVE WHERE WE STOP PEEKING
	GTTAB	%CNSJN		;GET JOB/SEGMENT INFORMATION
	SOS	T1		;DECREMENT TO HIGHEST JOB NUMBER
	HRRZM	T1,JOBMAX	;STORE
	HLRE	T2,T1		;GET NUMBER OF SEGMENTS
	MOVNS	T2		;FROM AOBJN TYPE TO A REAL NUMBER
	ADDI	T2,(T1)		;NUMBER OF JOBS + SEGMENTS
	MOVEM	T2,JBTMXL	;STORE FOR GETTAB SIMULATOR
	GTTAB	%CNPDB		;FIND OUT BASE OF PDB'S
	MOVEM	T1,PDBPTR	;STORE IT TOO
	GTTAB	<.GTIDX,,.GTSLF> ;BASE OF RANGE TABLE FOR GETTABS
	HRRZM	T1,RNGTAB	;STORE THAT TOO
	GTTAB	<.GTUPM,,.GTSLF> ;BASE OF JOB UPMP TABLE
	HRRZS	T1		;ISOLATE ADDRESS
	ADD	T1,[Z MONITR(J)] ;FUTURE INDIRECT REFERENCES
	MOVEM	T1,JBTUPM	;STORE ADDRESS OF JBTUPM
	GTTAB	<.GTSTS,,.GTSLF> ;BASE OF JOB STATUS TABLE
	HRRZS	T1		;ISOLATE ADDRESS
	ADD	T1,[Z MONITR(J)] ;FUTURE INDIRECT REFERENCES
	MOVEM	T1,JBTSTS	;STORE ADDRESS OF JBTSTS
	GTTAB	<.GTADR,,.GTSLF> ;BASE OF JOB ADDRESS TABLE
	HRRZS	T1		;ISOLATE ADDRESS
	ADD	T1,[Z MONITR(J)] ;FUTURE INDIRECT REFERENCES
	MOVEM	T1,JBTADR	;STORE ADDRESS OF JBTADR
	GTTAB	<.GTPRV,,.GTSLF> ;HACK COMING
	HRRZS	T1		;ISOLATE ADDRESS
	SUB	T1,JOBMAX	;JBTAD2 IS NOT GETTABABLE
	SUB	T1,JOBMAX	;BUT IT IS JBTPRV-2*JOBN
	SUBI	T1,2		;ACCOUNT FOR TWICE THE NULL JOB REMOVED ABOVE
	ADD	T1,[Z MONITR(J)] ;FUTURE INDIRECT REFERENCES
	MOVEM	T1,JBTAD2	;STORE IT (HACK)
	GTTAB	%CNFRE		;POINTER TO FREE CORE BIT MAP
	MOVEM	T1,FREPTR	;STORE
	HLRE	T1,T1		;SIZE OF TABLE
	MOVNS	T1		;TO A REAL NUMBER
	IMULI	T1,^D36		;TO CHUNKS AVAILABLE
	MOVEM	T1,FREAVB	;STORE FOR PERCENT COMPUTATIONS
	GTTAB	%CNLOC		;WHERE FREE CORE STARTS
	MOVEM	T1,LOCORE	;STORE
	GTTAB	%CNFRU		;CURRENT AMOUNT USED
	MOVEM	T1,FRUSED	;STORE
	FORMAT	<<Free Core Used = >,<OCT4 FRUSED>,< Words = >,<PER>,,<CRLF>>
	PUSHJ	P,RTNPDB	;ACCOUNT FOR PDB SPACE
	PUSHJ	P,RTNPSI	;GET PSISER DATA BASE
	PUSHJ	P,RTNSTR	;GET STR DATA BASE, SAT, SPT
	PUSHJ	P,RTNCPY	;RETURN UPDATE FILE RIB POINTERS
	PUSHJ	P,RTNDDB	;ANY DDBS CARVED OUT OF FREE SPACE
	PUSHJ	P,RTNIPC	;DO IPCF RECEIVE QUEUES
;	PUSHJ	P,RTNLNM	;RETURN JOBS LOGICAL NAME TABLES
	PUSHJ	P,RTNPTH	;RETURN PATH BLOCKS FOR EXE'S FROM SFD'S
	PUSHJ	P,RTNCTX	;RETURN SAVED CONTEXT BLOCKS
	PUSHJ	P,RTNENQ	;RETURN ENQ/DEQ LOCK BLOCKS
	PUSHJ	P,RTNNET	;NETSER STUFF
	PUSHJ	P,RTNDTE	;RETURN DTESER STUFF
	PUSHJ	P,RTNCSH	;RETURN DISK CACHE STUFF
	PUSHJ	P,RTNEBM	;RETURN EXTENSIBLE BITMAP MEMORY
	PUSHJ	P,RTNDAE	;RETURN DAEMON ERROR STUFF
	PUSHJ	P,RTNNRT	;*** MUST BE LAST *** RETURN NRTSER STUFF
	JRST	LEFT		;TELL WHATS LEFT OVER
;HERE TO ACCOUNT FOR PDB SPACE USED BY JOBS

RTNPDB:	MOVEI	P1,PDBLEN	;NUMBER OF WORDS IN A PDB
	MOVE	P2,PDBPTR	;ADDR OF JBTPDB
	MOVSI	P3,'PDB'	;TEXT FOR TYPEOUT

RTNCOM:	MOVE	J,JOBMAX	;FOR ALL JOBS
	SETZM	FRERTN		;START COUNTS FRESH
RTNC.1:	DMOVE	T1,P1		;SIZE  AND JBTXXX BASE
	ADDI	T2,(J)		;FOR JOB N
	HRRZ	T2,MONITR(T2)	;GET TABLE ADDRESS
	SKIPE	T2		;ANY THERE
	PUSHJ	P,GIVWDS	;YES, RETURN IT
	SOJGE	J,RTNC.1	;GET ALL INCLUDING THE NULL JOB
	FORMAT	<,<SIX P3>,< Space is >,<OCT4 FRERTN>>
	JRST	CRPOPJ		;CRLF AND EXIT

;HERE TO ACCOUNT FOR PSISER DATA BASE

RTNPSI:	GTTAB	%CNPIL		;LENGTH OF PSI DATA BASE
	MOVE	P1,T1		;COPY SIZE
	MOVEM	T1,PITSIZ	;SAVE FOR LATER
	GTTAB	%CNPIA		;ADDRESS OF JBTPIA
	MOVE	P2,T1		;COPY IT
	MOVSI	P3,'PSI'	;TEXT FOR TYPE OUT
	JRST	RTNCOM		;USE COMMON CODE

;HERE TO ACCOUNT FOR PATH BLOCKS FOR EXE FILES RUN FROM SFD'S

RTNPTH:	SETZM	FRERTN		;START FRESH
	MOVE	J,JBTMXL	;HIGHEST SEGMENT NUMBER
PTH.1:	GTTAB	<-1,,.GTPPN>	;JBTPPN FOR EXE FILE
	SKIPN	T2,T1		;COPY ADDRESS
	JRST	PTH.2		;NEVER MIND
	MOVEI	T1,PTHLEN	;NUMBER OF WORDS TO RETURN
	TLNN	T2,-1		;WAIT, IS THAT REALLY A PPN LIKE THE OLD DAYS
	PUSHJ	P,GIVWDS	;NOPE, RETURN IT
PTH.2:	CAMLE	J,JOBMAX	;INTO REAL JOB TABLES YET
	SOJA	J,PTH.1		;NO, KEEP GOING
	FORMAT	<<High Seg PATH. Block Space is >,<OCT4 FRERTN>>
	JRST	CRPOPJ		;RETURN
;HERE TO ACCOUNT FOR JOB LOGICAL NAME TABLE

REPEAT 0,<;REMOVED FROM 7.04
RTNLNM:	SETZM	FRERTN		;START FRESH
	MOVE	J,JOBMAX	;FOR ALL JOBS
LNM.1:	GTTAB	<-1,,.GTDVL>	;LOGICAL NAME TABLE
	HRRE	T2,T1		;WHERE IT IS
	MOVEI	T1,LNMLEN	;NUMBER OF WORDS
	SKIPLE	T2		;IS THERE ONE
	PUSHJ	P,GIVWDS	;YES, RETURN IT
	SOJG	J,LNM.1		;GET ALL JOBS
	FORMAT	<<Logical Name Space is >,<OCT4 FRERTN>>
	JRST	CRPOPJ		;RETURN
> ;END REPEAT 0


;HERE TO ACCOUNT FOR COPIES OF RIB POINTERS FOR UPDATE FILES

RTNCPY:	SETZM	FRERTN		;START FRESH
	GTTAB	%LDPTR		;GET POINTER TO FIRST UPDATE FILE RIB POINTER COPY
	HLRZ	P1,T1		;COPY IT
CPY.1:	JUMPE	P1,CPY.2	;ALL DONE
	MOVE	T2,P1		;ADDRESS OF BLOCK
	MOVEI	T1,PTRCOR	;SIZE OF THE BLOCK
	PUSHJ	P,GIVWDS	;RETURN THE SPACE
	HLRZ	P1,PTRSYS(P1)	;STEP TO NEXT BLOCK
	JRST	CPY.1		;GET THEM ALL
CPY.2:	FORMAT	<<File Pointer Copy Space is >,<OCT4 FRERTN>>
	JRST	CRPOPJ		;AND RETURN
;HERE TO ACCOUNT FOR SAVED CONTEXT BLOCKS

RTNCTX:	SETZM	FRERTN		;START FRESH
	MOVE	J,JOBMAX	;FOR EACH JOB
CTX.1:	MOVE	P1,J		;COPY JOB NUMBER
	ADD	P1,PDBPTR	;ADDRESS OF JBTPDB FOR JOB
	HRRZ	P1,MONITR(P1)	;GET ADD OF PDB ITSELF
	JUMPE	P1,CTX.5	;NONE, GET ANOTHER JOB
	HRRZ	T2,MONITR+.PDSCX(P1) ;GET ADDRESS OF SAVED CONTEXT BLOCK
	JUMPE	T2,CTX.2	;NONE
	MOVEI	T1,NWSCTX	;WORDS IN A CONTEXT BLOCK
	CAMGE	T2,FYSORG	;MIGHT BE IN FUNNY SPACE
	PUSHJ	P,GIVWDS	;ISN'T, RETURN LOW CORE
CTX.2:	MOVE	P3,MONITR+.PDCTC(P1) ;GET CURRENT CONTEXT
	MOVE	T2,MONITR+.PDSAC(P1) ;GET START OF CONTEXT CHAIN
CTX.3:	SKIPN	P2,T2		;COPY ADDRESS
	JRST	CTX.5		;NONE?
	MOVEI	T1,.CTSIZ	;NUMBER OF WORDS
	TLNN	T2,-1		;NZS ADDRESS?
	PUSHJ	P,GIVWDS	;RETURN THEM
;REPEAT 0,<			;THIS DOESN'T WORK?
	MOVE	T1,P2		;ADDRESS OF THIS BLOCK
	ADDI	T1,.CTBPR+.CXPIA ;OFFSET TO POINTER TO SAVED JBTPIA BLOCK
	PUSHJ	P,WDFTCH	;GET IT
	CAME	P2,P3		;IGNORE THE CURRENT CTX
	SKIPN	T2,T1		;COPY ADDRESS
	JRST	CTX.3A		;NOTHING
	MOVE	T1,PITSIZ	;SIZE OF A BLOCK
	PUSHJ	P,GIVWDS	;RETURN IT
;>; END REPEAT 0
CTX.3A:
;REPEAT 0,<			;THIS DOESN'T WORK?
	CAMN	P2,P3		;THE "CURRENT" CONTEXT?
	JRST	CTX.4		;YES, IGNORE SAVED CONTEXT BLOCK
	MOVE	T1,P2		;ADDRESS OF THIS BLOCK
	ADDI	T1,.CTBPR+.CXSCX ;OFFSET TO POINTER TO SAVED CONTEXT BLOCK
	PUSHJ	P,WDFTCH	;GET IT
	SKIPN	T2,T1		;COPY ADDRESS
	JRST	CTX.4		;NOTHING THERE, DON'T TRY TO RETURN IT
	MOVEI	T1,NWSCTX	;WORDS IN A CONTEXT BLOCK
	CAMGE	T2,FYSORG	;MIGHT BE IN FUNNY SPACE
	PUSHJ	P,GIVWDS	;ISN'T, RETURN LOW CORE
;>; END REPEAT 0
CTX.4:	MOVE	T1,P2		;ADDRESS OF THIS BLOCK
	ADDI	T1,.CTNXT	;OFFSET TO LINK WORD
	PUSHJ	P,WDFTCH	;GET IT
	MOVE	T2,T1		;COPY ADDRESS
	JRST	CTX.3		;GIVE IT BACK
CTX.5:	SOJG	J,CTX.1		;AND GET ALL THE JOBS
	FORMAT	<<Saved Context Space is >,<OCT4 FRERTN>>
	JRST	CRPOPJ		;AND RETURN
;HERE TO ACCOUNT FOR STUFF REQUIRED BY DISK STRUCTURES

RTNSTR:	GTTAB	%LDSTR		;FIRST STRUCTURE IN SYS
	HLRZ	P1,T1		;PUT IN SAFER PLACE
	SETZ	P5,		;CLEAR TOTAL COUNT
STR.1:	JUMPE	P1,STR.7	;DONE IF LAST STR
	SKIPN	STRNAM(P1)	;A REAL STRUCTURE THERE
	JRST	STR.6		;NO, DON'T BOTHER
	SETZM	FRERTN		;START COUNTS OVER FOR EACH STR
	MOVE	T2,P1		;WHERE STR DATA BLOCK IS
	MOVEI	T1,STRLEN	;AND HOW LONG IT IS
	CAML	T2,LOCORE	;MOUNTED AT ONCE TIME
	PUSHJ	P,GIVWDS	;NO, REMOVE THE CORE
	HLRZ	P2,STRUNI(P1)	;STEP TO FIRST UNIT IN STR
STR.2:	JUMPE	P2,STR.5	;LAST UNIT, GO TO NEXT STR
	MOVEI	T1,UNISAB(P2)	;GET ADDRESS OF WORD WE WANT
	PUSHJ	P,WDFTCH	;GET IT
	SKIPE	P3,T1		;GET SAT BLOCK TABLE ADDRESS
	TLZE	P3,-1		;SKIP THIS IF ITS NOT IN SECTION 0
	JRST	STR.4		;SKIP THIS WHOLE SAT
	MOVE	J,P3		;COPY WHERE RING STARTS
	LDB	P4,[POINT 9,UNIWPS(P2),8] ;GET SIZE OF SAT ON THIS UNIT
STR.3:	MOVE	T2,P3		;ADDR OF SAB
	MOVEI	T1,SABBIT(P4)	;SPACE ALLOCATED
	CAML	T2,LOCORE	;FROM ONCE
	PUSHJ	P,GIVWDS	;NO, RETURN THE SPACE
	MOVE	P3,SABRNG(P3)	;TO NEXT SAB IN RING
	JUMPE	P3,STR.3A	;CHECK LINK WORD
	CAIE	P3,(J)		;BACK WHERE WE STARTED
	JRST	STR.3		;NOPE, DO THE NEXT ONE
	JRST	STR.4		;DONE WOTH SAB RING, GET SPT
STR.3A:	FORMAT	<<SAB Ring Messed Up for >,<SIX UNINAM(P2)>,,<CRLF>>
STR.4:	MOVEI	T1,UNISPT(P2)	;ADDRESS OF THE SPT
	PUSHJ	P,WDFTCH	;GET IT
	TLZE	T1,-1		;UNLESS IN A NON-ZERO SECTION
	JRST	STR.4A		;SKIP THE SPT
	MOVE	T2,T1		;SAVE A COPY
	LDB	T1,[POINT 8,UNISPU(P2),17] ;SIZE OF THE SPT ON THIS UNIT
	ADDI	T1,SPTFIR+1	;PLUS OVERHEAD
	CAML	T2,LOCORE	;IN FREE CORE
	PUSHJ	P,GIVWDS	;RETURN IT
STR.4A:	MOVEI	T1,UNISTR(P2)	;WORD WE WANT
	PUSHJ	P,WDFTCH	;GET IT
	HLRZ	P2,T1		;STEP TO NEXT UNIT IN STRUCTURE
	JRST	STR.2		;AND DO THAT ONE
STR.5:	SKIPN	T1,FRERTN	;DON'T BOTHER IF NO SPACE RECLAIMED
	JRST	STR.6		;NONE, TRY ANOTHER
	ADD	P5,T1		;ACCUMULATE TOTAL
	FORMAT	<,<SIX STRNAM(P1)>,<: >,<OCT4 T1>,< Words>,<CRLF>>
STR.6:	HLRZ	P1,STRSYS(P1)	;TO NEXT FILE STRUCTURE
	JRST	STR.1		;AND DO IT
STR.7:	FORMAT	<<Total File Structure Space is >,<OCT4 P5>>
	JRST	CRPOPJ		;AND RETURN
;HERE TO ACCOUNT FOR ENQ/DEQ LOCK BLOCKS

RTNENQ:	GTTAB	%CNHSH		;-LEN,,ADDR OF HSHTAB
	HLRE	J,T1		;GET -VE LENGTH
	MOVMS	J		;MAKE +VE
	MOVEI	P1,-1(T1)	;POINT TO LAST ENTRY IN HSHTAB
	ADDI	P1,(J)		;...
	SETZM	FRERTN		;START FRESH
ENQ.1:	HRRZ	P2,.LBNHS(P1)	;FIRST LOCK BLOCK OFF THIS ENTRY
ENQ.2:	CAIN	P2,(P1)		;CHAIN ENDS WHEN WE GET BACK TO HSHTAB
	JRST	ENQ.5		;LOOK AT NEXT HSHTAB ENTRY
	HRRZ	P3,.LBNQ(P2)	;FIRST Q-BLOCK
ENQ.3:	CAIN	P3,(P2)		;BACK TO THE LOCK BLOCK
	JRST	ENQ.4		;YES, DONE WITH Q-BLOCKS
	MOVE	T2,P3		;ADDR OF Q-BLOCK
	MOVEI	T1,QBSIZE	;AND LENGTH OF IT
	HRRZ	P4,.QBMSK(P3)	;POINT TO ANY MASK BLOCK OWNED
	HRRZ	P3,.QBNQ(P3)	;NEXT Q-BLOCK IN CHAIN
	PUSHJ	P,GIVWDS	;RETURN THIS BLOCK
	JUMPE	P4,ENQ.3	;GET NEXT Q-BLOCK IF NO MASK BLOCK
	MOVE	T2,P4		;ADDRESS OF IT
	HLRZ	T1,.LBNMS(P2)	;LENGTH OF IT
	PUSHJ	P,GIVWDS	;RETURN MASK BLOCK
	JRST	ENQ.3		;AND CHECK OUT NEXT Q-BLOCK
ENQ.4:	MOVE	T2,P2		;ADDRESS OF THE BLOCK
	HLRZ	T1,.LBLEN(P2)	;LENGTH OF THE BLOCK
	PUSHJ	P,GIVWDS	;RETURN THE SPACE
	HRRZ	P2,.LBNHS(P2)	;NEXT BLOCK IN THE CHAIN
	JRST	ENQ.2		;CHECK IT OUT
ENQ.5:	SOS	P1		;BACK DOWN HSHTAB
	SOJG	J,ENQ.1		;TRY NEXT ENTRY
	FORMAT	<<ENQ/DEQ Lock Block Space is >,<OCT4 FRERTN>>
	JRST	CRPOPJ		;AND RETURN
;HERE TO ACCOUNT FOR DDB'S BUILT IN FREE CORE
;WARNING:
;	DO NOT RETURN NETWORK DDB'S IN THIS ROUTINE

RTNDDB:	FORMAT	<<Scanning free core for DDB's>,<CRLF>>
	SETZM	FRERTN		;START FRESH
	GTTAB	%CNDEV		;START OF DDB CHAIN
	HLRZ	P2,T1		;SAVE ADDRESS OF FIRST DDB
DDB.1:	CAMGE	P2,LOCORE	;IN FREE SPACE
	JRST	DDB.2		;NO, TRY ANOTHER
	CAML	P2,LOWLIM	;UP IN MONITORS HIGHSEG (DSKDDB)
	JRST	DDB.2		;YES, QUIT NOW, MAY LOSE SOME DDBS
	FORMAT	<<	>,<SIX DEVNAM(P2)>,< at >,<OCT P2>,< size >>
	HLLZ	T4,DEVNAM(P2)	;GET WHAT IT IS
	MOVE	T2,P2		;ADDRESS FOR RETURN
	SETZ	T1,		;IN CASE WE DON'T KNOW ABOUT IT
	MOVE	T3,DEVMOD(P2)	;GET DEVMOD
	TLNE	T3,DVDSK	;IS IT A "FAKE" DISK DDB
	JRST	[MOVEI T1,DSKDDS ;YES, GET DISK DDB SIZE
		 JRST DDB.0]	;AND RETURN THE SPACE
	MOVSI	T3,-NUMDVS	;NUMBER HARD-WIRED
	CAME	T4,DVSNMS(T3)	;LOOK FOR IT
	AOBJN	T3,.-1		;TRY NEXT
	SKIPGE	T3		;KNOWN
	XCT	DVSLDS(T3)	;YES, GET SIZE VALUE
DDB.0:	FORMAT	<,<OCT T1>,,<CRLF>>
	SKIPE	T1		;KNOW THE SIZE
	PUSHJ	P,GIVWDS	;YES, RETURN SOME
DDB.2:	MOVEI	T1,DEVSER(P2)	;ADDRESS TO FETCH
	CAMGE	T1,LOWLIM	;DOES IT FIT?
	SKIPA	T1,MONITR(T1)	;YES--JUST GRAB IT
	PUSHJ	P,WDFTCH	;NO--GET IT THE HARD WAY
	HLRZ	P2,T1		;STEP TO NEXT DEVICE
	JUMPN	P2,DDB.1	;LOOK AT IT
DDB.3:	FORMAT	<<DDB Space is >,<OCT4 FRERTN>>
	JRST	CRPOPJ		;RETURN
DVSNMS:	SIXBIT	/MPX/		;MPX DEVICE
	SIXBIT	/'LA/		;MTA LABEL DDB
	SIXBIT	/'LB/		;MTB LABEL DDB
	SIXBIT	/'LC/		;MTC LABEL DDB
	SIXBIT	/'LD/		;MTD LABEL DDB
	SIXBIT	/'LE/		;MTE LABEL DDB
	SIXBIT	/'LF/		;MTF LABEL DDB
NUMDVS==.-DVSNMS		;NUMBER KNOWN

DVSLDS:	PUSHJ	P,DVSMPX	;MPX IS SPECIAL
	MOVEI	T1,SPROTO	;LENGTH OF A MAG TAPE LABEL DDB
	MOVEI	T1,SPROTO	;LENGTH OF A MAG TAPE LABEL DDB
	MOVEI	T1,SPROTO	;LENGTH OF A MAG TAPE LABEL DDB
	MOVEI	T1,SPROTO	;LENGTH OF A MAG TAPE LABEL DDB
	MOVEI	T1,SPROTO	;LENGTH OF A MAG TAPE LABEL DDB
	MOVEI	T1,SPROTO	;LENGTH OF A MAG TAPE LABEL DDB

DVSMPX:	MOVEI	T1,MPXLEN	;SIZE OF MPX DDB
	FORMAT	<,<OCT T1>,,<CRLF>>
	PUSHJ	P,GIVWDS	;RETURN DDB
	HLRZ	T2,DEVXTR(P2)	;ADDRESS OF CDT
	SKIPE	T1,T2		;MIGHT NOT BE ANY
	HLRZ	T1,MONITR(T2)	;LENGTH OF CDT
	FORMAT	<<		CDT at >,<OCT T2>,< size >>
	POPJ	P,		;RETURN TO GIVE BACK CDT INSTEAD OF DDB
;HERE TO ACCOUNT FOR IPCF RECEIVE QUEUES

RTNIPC:	FORMAT	<<Scanning IPCF Receive Queues>,<CRLF>>
	SETZM	FRERTN		;START FRESH
	MOVE	J,JOBMAX	;GET ALL JOBS
IPC.1:	GTTAB	<-1,,.GTIPP>	;IPCF POINTERS FOR JOB (J)
	HLRZ	P2,T1		;GET ADDRESS OF FIRST MESSAGE
	ANDI	T1,777		;ISOLATE COUNT OF MESSAGES
	JUMPE	T1,IPC.3	;NONE, GET NEXT JOB
	FORMAT	<<	Job >,<DEC J>,< has >,<DEC T1>,< messages>,<CRLF>>
IPC.2:	JUMPE	P2,IPC.3	;NEXT JOB
	MOVE	T2,P2		;FOR RETURN
	SKIPGE	MONITR+.IPCFP(P2) ;SKIP IF NOT ON DISK
	JRST	[SETZ T1,	;NOT IN CORE, GET A ZERO
		 JRST IPC.2A]	;CONTINUE
	MOVEI	T1,IP.CFV	;PAGE MODE?
	TDNE	T1,MONITR+.IPCFL(P2) ;IN PACKET HEADER?
	JRST	[LDB T1,[POINT 21,MONITR+.IPCFP(P2),35] ;GET PAGE NUMBER
		 FORMAT	<<		Page >,<OCT T1>,< is in-core>,<CRLF>>
		SETZ T1,	;ZERO LENGTH
		JRST IPC.2A]	;CONTINUE
	LDB	T1,[POINT 10,MONITR+.IPCFP(P2),12] ;GET LENGTH
IPC.2A:	ADDI	T1,.IPCFC+1	;PLUS OVERHEAD
	PUSHJ	P,GIVWDS	;RETURN IT
IPC.2B:	HLRZ	P2,MONITR+.IPCFL(P2) ;LINKED THROUGH LH OF FLAG WORD
	JRST	IPC.2		;AND TRY THAT
IPC.3:	SOJG	J,IPC.1		;GET ALL THE JOBS
	FORMAT	<<IPCF Space is >,<OCT4 FRERTN>>
	JRST	CRPOPJ		;RETURN
;HERE TO ACCOUNT FOR NETWORK FREE CORE
;ASSUMPTIONS:
;	NETSER HAS "PARANOID" AND "P$COR" TURNED ON
;	%NTMEM IS NOT GETTABABLE BUT IS "NETGTT-1" (HACK)

RTNNET:	GTTAB	<.GTNTP,,.GTSLF> ;ADDRESS OF NETGTT
	TLNN	T1,777000	;CHECK TABLE LENGTH
	POPJ	P,		;ZERO, GETTAB REMOVED
	MOVEI	P1,-1(T1)	;POINT TO %NTMEM ( I KNOW )
	SETZM	FRERTN		;START COUNT FRESH
NET.1:	HRRZ	P1,MONITR(P1)	;NEXT ITEM ON NETWORK LIST
	JUMPE	P1,NET.3	;DONE ON ZERO LINK
	MOVEI	T1,1		;THERE IS NO COUNT WORD, MUST COMPUTE LENGTH
	MOVEI	T2,(P1)		;WHERE IT STARTS
	MOVEI	T3,(P1)		;AND A WORKING COPY
NET.2:	MOVE	T4,MONITR(T3)	;GET A WORD
	CAME	T4,[SIXBIT/NETMEM/] ;THIS PATTERN IS THE LAST WORD OF THE SPACE
	AOJA	T1,[AOJA T3,NET.2] ;NOT END, COUNT WORD AND GO TO NEXT ONE
	PUSHJ	P,GIVWDS	;RETURN THE SPACE
	JRST	NET.1		;AND GET NEXT CHUNK
NET.3:	FORMAT	<<NETWORK Space is >,<OCT4 FRERTN>,< (NETSER Claims it knows >,<GTTO [%NTCOR]>,<)>,<CRLF>>
	POPJ	P,		;DONE WITH NETWORKS


;HERE TO ACCOUNT FOR NRTSER FREE CORE (AS MUCH AS WE CAN)
;NOTE:  NRTSER USES NO LINKED LISTS TO KEEP TRACK OF ALLOCATED
;CORE.  WE DEPEND ON HIM STORING THE ADDRESS OF EVERY CHUNK
;OF MEMORY ALLOCATED IN HIS "CHANNEL TABLE".

RTNNRT:	SETZM	FRERTN		;START COUNTS FRESH
	GTTAB	%DNNCH		;GET ADDRESS OF NRTSER'S CHANNEL TABLE POINTER
	JUMPE	T1,CPOPJ	;RETURN IF NO TABLE
	MOVE	P1,MONITR(T1)	;GET THE TABLE ADDRESS
	HRRZ	T2,MONITR+3(T1)	;GET POINTER TO NRTSER'S SAB
	HLRZ	T1,MONITR-1(T2)	;GET CHECK WORD
	CAIE	T1,'NRT'	;SHOULD BE THIS
	POPJ	P,		;NOPE
	HRRZ	T1,MONITR-1(T2)	;GET LENGTH
	ADDI	T1,1		;ACCOUNT FOR NRTSER'S LEADING TAG WORD
	SUBI	T2,1		;POINT AT REAL START OF BLOCK
	PUSHJ	P,GIVWDS	;RETURN THE SPACE
	HLRZ	T1,MONITR-1(P1)	;GET THE LH OF FIRST WORD
	CAIE	T1,'NRT'	;SHOULD BE THIS
	POPJ	P,		;NOT, WE DON'T KNOW WHAT TO DO HERE
	HRRZ	T1,MONITR-1(P1)	;GET LENGTH OF HIS TABLE
	MOVN	T2,T1		;NEGATE LENGTH
	HRL	P1,T2		;MAKE AN AOBJN POINTER
	ADDI	T1,1		;ACCOUNT FOR NRTSER'S LEADING TAG WORD
	MOVEI	T2,-1(P1)	;POINT AT REAL START OF BLOCK
	PUSHJ	P,GIVWDS	;RETURN THE SPACE
NRT.1:	SKIPN	T2,MONITR(P1)	;GET AN ENTRY FROM CHANNEL TABLE
	JRST	NRT.2		;NOTHING THERE
	HLRZ	T1,MONITR-1(T2)	;GET THE CHECK WORD
	CAIE	T1,'NRT'	;NRTSER'S TAG?
	JRST	NRT.2		;NOPE, LEAVE IT ALONE
	HRRZ	T1,MONITR-1(T2)	;GET SIZE OF BLOCK
	ADDI	T1,1		;ACCOUNT FOR NRTSER'S LEADING TAG WORD
	MOVEI	T2,-1(T2)	;POINT AT REAL START OF BLOCK
	PUSHJ	P,GIVWDS	;RETURN THE SPACE
NRT.2:	AOBJN	P1,NRT.1	;LOOP FOR ALL ENTRIES
	FORMAT	<<NRTSER Space is >,<OCT4 FRERTN>>
	JRST	CRPOPJ		;RETURN
;HERE TO ACCOUNT FOR HASH BLOCKS IN THE DISK CACHE AND THE DATA
;BLOCKS (KS ONLY).

RTNCSH:	GTTAB	%LDCHD		;GET HEADER OF CACHE LIST
	MOVE	P1,T1		;SAVE IT HERE
	SETZM	FRERTN		;START COUNTS FRESH

	MOVEI	T1,.CBNHB(P1)	;POINTER TO FREE LIST
	MOVE	P2,T1		;SAVE START
	PUSHJ	P,WDFTCH	;GET IT
CSH.1:	CAMN	T1,P2		;HIT THE END YET?
	JRST	CSH.2		;YES
	MOVE	P3,T1		;SAVE BLOCK ADDRESS
	ADDI	T1,.CBDAT	;OFFSET TO DATA BLOCK
	PUSHJ	P,WDFTCH	;GET IT
	MOVE	T2,T1		;COPY ADDRESS
	MOVEI	T1,DSKBLK	;SIZE OF A BLOCK
	TLNN	T2,-1		;NON-ZERO SECTION?
	PUSHJ	P,GIVWDS	;RETURN BLOCK
	MOVEI	T1,.CBLEN	;LENGTH OF BLOCK
	MOVE	T2,P3		;BLOCK ADDRESS
	MOVEI	T1,.CBNHB(P3)	;LINK TO NEXT BLOCK
	PUSHJ	P,WDFTCH	;GET IT
	JRST	CSH.1		;CHECK IT

CSH.2:	MOVEI	T1,.CBNAB(P1)	;POINTER TO ACTIVE LIST
	PUSHJ	P,WDFTCH	;GET IT
CSH.3:	CAMN	T1,P2		;HIT THE END YET?
	JRST	CSH.4		;YES
	MOVE	P3,T1		;SAVE BLOCK ADDRESS
	ADDI	T1,.CBDAT	;OFFSET TO DATA BLOCK
	PUSHJ	P,WDFTCH	;GET IT
	MOVE	T2,T1		;COPY ADDRESS
	MOVEI	T1,DSKBLK	;SIZE OF A BLOCK
	TLNN	T2,-1		;NON-ZERO SECTION?
	PUSHJ	P,GIVWDS	;RETURN BLOCK
	MOVEI	T1,.CBLEN	;LENGTH OF BLOCK
	MOVE	T2,P3		;BLOCK ADDRESS
	PUSHJ	P,GIVWDS	;RETURN IT
	MOVEI	T1,.CBNAB(P3)	;LINK TO NEXT BLOCK
	PUSHJ	P,WDFTCH	;GET IT
	JRST	CSH.3		;CHECK IT

CSH.4:	FORMAT	<<Disk Cache Space is >,<OCT4 FRERTN>>
	JRST	CRPOPJ		;RETURN
;HERE TO ACCOUNT FOR EXTENSIBLE BITMAP MEMORY BLOCKS

RTNEBM:	SETZM	FRERTN		;START COUNTS FRESH
	GTTAB	%CNAHB		;GET FIRST ALLOCATION HEADER BLOCK
	MOVE	P1,T1		;SAVE IT HERE
EBM.1:	MOVE	P2,MONITR+AHBAEB(P1) ;GET FIRST EXTENT BLOCK
EBM.2:	HLRE	T1,MONITR+AEBBMP(P2) ;GET LENGTH OF BITMAP
	MOVMS	T1		;MAKE +VE
	ADDI	T1,AEBBMP+1	;INCLUDE HEADER
	MOVE	T2,P2		;ADDRESS OF EXTENT BLOCK
	CAML	T2,LOCORE	;DON'T RETURN ASSEMBLED-IN BLOCKS
	CAML	T2,LOWLIM	;...
	SKIPA			;NO GOOD
	PUSHJ	P,GIVWDS	;RETURN THE SPACE
	MOVE	P2,MONITR+AEBNXT(P2) ;GET LINK TO NEXT BLOCK
	JUMPN	P2,EBM.2	;JUMP FOR NEXT ONE
	MOVE	P1,MONITR+AHBNXT(P1) ;GET NEXT HEADER BLOCK
	JUMPN	P1,EBM.1	;JUMP FOR NEXT ONE
	FORMAT	<<Extensible Bitmap Memory Space is >,<OCT4 FRERTN>>
	JRST	CRPOPJ		;RETURN
;HERE TO ACCOUNT FOR ANY MESSAGE BUFFERS USED FOR DECNET OVER DTE.

RTNDTE:	SETZM	FRERTN		;START COUNT FRESH
	GTTAB	%DNETH		;GET POINTER TO DTE TABLE
	SKIPN	P1,T1		;COPY ADDRESS, SKIP IF THERE IS ONE
	POPJ	P,		;NONE
	GTTAB	%CNCPU		;NUMBER OF CPU'S
	MOVNS	T1		;NEGATE
	HRL	P1,T1		;BUILD AN AOBJN WORD
DTE.1:	MOVE	P2,MONITR(P1)	;GET ADDRESS OF A DTE BLOCK
	HRLI	P2,-4		;MAXIMUM OF 4 DTE'S
DTE.2:	MOVE	P3,MONITR(P2)	;GET DTE CONTROL BLOCK ADDRESS
	MOVEI	T1,UBLSIZ+6	;SIZE
	SKIPE	T2,MONITR+ETDOBK(P3) ;AN OUTPUT BUFFER?
	PUSHJ	P,GIVWDS	;YES, RETURN IT
	MOVEI	T1,UBLSIZ+6	;SIZE
	SKIPE	T2,MONITR+ETDIBK(P3) ;AN INPUT BUFFER?
	PUSHJ	P,GIVWDS	;YES, RETURN IT
	AOBJN	P2,DTE.2	;LOOP FOR DTE'S ON THIS CPU
	AOBJN	P1,DTE.1	;LOOP FOR ALL DTE'S
	FORMAT	<<DTE Buffer Space is >,<OCT4 FRERTN>>
	JRST	CRPOPJ		;RETURN
	SETZM	FRERTN		;START COUNT FRESH
;HERE TO ACCOUNT FOR ANY FREE CORE USED BY DAEMON ERROR ENTRIES
;RIGHT NOW ONLY CODE 30 (KLEERR) AND INDIRECTLY CODE NN (SYSTEM
;ERROR BLOCKS).

RTNDAE:	POPJ	P,		;DONE
	GTTAB	%LDESZ		;GET LENGTH OF ERPTBK ENTRY
	SKIPN	T1		;ANYTHING?
	MOVEI	T1,2		;NO, USE OLD DEFAULT
	MOVEM	T1,ERPTSZ	;SAVE SIZE
	GTTAB	%LDERT		;ADDRESS OF ERPTBK
	SKIPN	T1		;ANYTHING?
	HALT	.		;NO, HANDLE SOME DAY
	MOVEM	T1,ESVIDX	;SAVE
	GTTAB	%LDPT1		;POINTER TO EXTRACT ENTRIES
	PUSHJ	P,WDFTCH	;FETCH THE WORD
	SKIPN	T1		;IF INITIAL IS ZERO
	MOVE	T1,ERPTSZ	;OTHER ENTRY IS BLANK
	MOVEI	T3,(T1)		;COPY INITIAL OFFSET
	GTTAB	%LDLTH		;GET MAX TABLE LENGTH
	MOVEM	T1,ERPTMX	;SAVE IT TOO
	GTTAB	%CNFRE		;POINTER TO FREE CORE BIT MAP
;HERE TO REPORT STUFF LEFT OVER

LEFT:	SKIPN	FRUSED		;ANYTHING LEFT OVER?
	JRST	LEFT.4		;NOPE
	FORMAT	<,<CRLF>,,<PER>,< Chunks (>,<OCT4 FRUSED>,< Words) unaccounted for:>,<CRLF>>
	MOVE	P1,FREPTR	;AOBJN FOR BIT MAP
	ADDI	P1,MONITR	;OFFSET FOR WHERE WE PUT THE MONITOR
	HRLI	P1,(POINT 1,0)	;LOOK AT A BIT AT A TIME
	MOVE	J,FREAVB	;MAX POSSIBLE( i.e. NUMBER OF BITS TO LOOK AT)
	MOVE	P2,LOCORE	;WHERE THEY ARE
	SETZB	P3,P4		;CLEAR COUNTERS
LEFT.1:	ILDB	T1,P1		;GET A BIT
	JUMPN	T1,[AOS P3	;COUNT SPACE TAKEN
		    SKIPN P4	;FIRST 1 BIT SEEN
		    MOVE P4,P2	;YES, REMEMBER WHERE IT STARTS
		    JRST LEFT.2] ;AND GET ANOTHER BIT
	JUMPE	P4,LEFT.2	;END OF A TAKEN SLOT
	FORMAT	<<	>,<OCT4 P3>,< Words @ >,<OCT P4>,,<CRLF>>
	SETZB	P3,P4		;START LOOKING AGAIN
LEFT.2:	ADDI	P2,4		;STEP TO NEXT ADDRESS
	SOJG	J,LEFT.1	;GET ALL THE BITS
	JUMPE	P4,LEFT.3	;ANY AT THE END
	FORMAT	<<	>,<OCT4 P3>,< Words @ >,<OCT P4>,,<CRLF>>
LEFT.3:	POPJ	P,		;RETURN

LEFT.4:	OUTSTR	[ASCIZ /
All free core accounted for!
/]
	POPJ	P,		;RETURN
	SUBTTL	The "HELP" Command

%HELP:	OUTSTR	[ASCIZ/Commands are:/]
	MOVEI	P2,CMDHLP	;FIRST HELP TEXT
	SKIPA	P1,[-NUMCMD,,CMDTBL] ;AOBJN FOR MAIN COMMAND TABLE
HLPCOM:	OUTSTR	[ASCIZ/Arguments are:/]

;COMMON PART OF HELP TEXT FOR OTHER COMMAND PROCESSORS
;	P1 = AOBJN TO COMMAND TABLE
;	P2 = ADDRESS OF PARALLEL HELP TEXT TABLE

HELP.1:	OUTSTR	[BYTE (7)15,12,11,0] ;CR,LF,TAB
	MOVE	T1,(P1)		;GET A COMMAND FROM THE TABLE
	PUSHJ	P,SIXOUT	;OUTPUT IT
	OUTCHR	[11]		;ALIGN WITH A TAB
	OUTSTR	@(P2)		;TEXT FOR IT
	AOS	P2		;STEP TO NEXT HELP TEXT
	AOBJN	P1,HELP.1	;AND TRY ANOTHER
	JRST	CRPOPJ		;END LINE AND RETURN


	SUBTTL	The "DDT" Command

%DDT:	PUSHJ	P,FLUSH		;NO ARGUMENTS
	HRRZ	T1,74		;ADDRESS OF DDT
	JUMPN	T1,(T1)		;GO TO IT
	OUTSTR	[ASCIZ/?DDT not loaded/]
	JRST	CRPOPJ		;RETURN
	SUBTTL	Some Input Subroutines

;SUBROUTINE TO INPUT A SINGLE CHARACTER INTO CH
;	PUSHJ	P,GETONE
;	  RETURN HERE IF A SPECIAL CHARACTER
;	  RETURN HERE IF A NUMBER
;	  RETURN HERE IF A LETTER
;IF FL.RSC IS ON, THIS GETS THE LAST CHARACTER (TERMINATOR OF PREVIOUS)

GETONE:	TLNE	F,(FL.EOL)	;END OF LINE SEEN
	JRST	GETO.2		;YES, RETURN LINE FEED
	TLZE	F,(FL.RSC)	;WANT OLD CHARACTER AGAIN
	JRST	[MOVE CH,SAVCHR	;YES, GET SAVED CHARACTER
		JRST GETO.B]	;AND PROCESS IT
	INCHWL	CH		;NO, GET A CHARACTER
GETO.A:	MOVEM	CH,SAVCHR	;SAVE FOR RESCAN
GETO.B:	JUMPE	CH,GETONE	;IGNORE NULLS
	CAIN	CH,15		;CARRIAGE RETURN ??
	JRST	GETONE		;YES, PITCH THOSE
	CAIE	CH,7		;^G ??
	CAIN	CH,13		;^K ??
	JRST	GETO.1		;YES, MARK END OF TEXT AND RETURN LINE FEED
	CAIN	CH,14		;^L ??
	JRST	GETO.1		;YES, MARK END OF TEXT AND RETURN LINE FEED
	CAIE	CH,12		;LINE FEED ??
	CAIN	CH,33		;ALTMODE ??
	JRST	GETO.1		;YES, MARK END OF TEXT AND RETURN LINE FEED
	CAIN	CH,32		;^Z ??
	JRST	GETO.0		;YES, LIGHT LOTS OF BITS FOR ^Z
	CAIN	CH,11		;A TAB
	SKIPA	CH,[" "]	;YES, CONVERT TO SPACE
	CAIN	CH," "		;A SPACE
	POPJ	P,		;YES, TAKE "SPECIAL" RETURN
	CAIE	CH,"!"		;LOOK FOR COMMENTS
	CAIN	CH,";"		;...
	JRST	GETO.2		;FAKE AN END OF LINE
	CAIG	CH,"9"		;LOOK FOR DIGITS
	CAIGE	CH,"0"		;...
	SKIPA			;NOT A DIGIT
	JRST	CPOPJ1		;TAKE "DIGIT" EXIT
	CAIG	CH,"Z"+40	;LOWER CASE LETTER
	CAIGE	CH,"A"+40	;...
	SKIPA			;NOT LOWER CASE
	SUBI	CH," "		;CONVERT TO UPPER CASE
	CAIG	CH,"Z"		;NOW DO LETTER CHECK
	CAIGE	CH,"A"		;...
	POPJ	P,		;MUST BE A SPECIAL
CPOPJ2:	AOS	(P)		;TAKE "LETTER" EXIT
CPOPJ1:	AOS	(P)		;LOTS OF SKIP RETURNS
CPOPJ:	POPJ	P,		;RETURN

GETO.0:	TLO	F,(FL.UPZ)	;MARK ^Z FOR JMF
GETO.1:	TLO	F,(FL.ETX)	;MARK REAL END OF TEXT
GETO.2:	TLO	F,(FL.EOL)	;LIGHT FAKE END OF LINE
	MOVEI	CH,12		;RETURN LINE FEED
	POPJ	P,		;TAKE "SPECIAL" RETURN
GETO.3:	PUSHJ	P,CRPOPJ	;END ECHOING WITH CR,LF
	JRST	GETO.1		;AND MARK LINE AS COMPLETE



;SUBROUTINE TO SEARCH A TABLE FOR A COMMAND OR ARGUMENT
;CALL:	T1 = ITEM IN SIXBIT
;	T2 = MASK FOR CHARACTERS TYPED
;	T3 = AOBJN POINTER FOR TABLE TO SEARCH
;RTNS:	CPOPJ  = NOT IN THE TABLE
;	CPOPJ1 = AMBIGUOUS
;	CPOPJ2 = FOUND IT
;RETURNS T1 INTACT, T2 = RELATIVE INDEX FOR COMMAND, CLOBBERS T3,T4,T5

TABSRC:	MOVEI	T4,(T3)		;SAVE TABLE START ADDRESS
	PUSH	P,T2		;SAVE MASK TO USE
	SETZ	T2,		;CLEAR FOUND INDICATOR
TABS.1:	MOVE	T5,(T3)		;GET AN ITEM
	CAMN	T1,T5		;EXACT MATCH
	JRST	[MOVEI T2,(T3)	;YES, MARK WHERE WE FOUND IT
		JRST TABS.3]	;AND EXIT
	ANDCM	T5,(P)		;MASK TO AS MANY CHARS AS IN T1
	CAME	T1,T5		;NOW DO WE HAVE A MATCH
	JRST	TABS.2		;NO, TRY NEXT ENTRY IN TABLE
	JUMPN	T2,[POP P,(P)	;IF ALREADY HAVE 1 MATCH
		JRST CPOPJ1]	;GIVE AMBIGUOUS RETURN
	MOVEI	T2,(T3)		;SAVE ADDRESS OF THIS MATCH
TABS.2:	AOBJN	T3,TABS.1	;AND LOOK SOME MORE
TABS.3:	POP	P,(P)		;CLEAN STACK NOW
	JUMPE	T2,CPOPJ	;RETURN IF NEVER FOUND ONE
	SUBI	T2,(T4)		;COMPUTE RELATIVE OFFSET OF COMMAND
	JRST	CPOPJ2		;AND GIVE LOTS OF SKIP RETURNS
;SUBROUTINE TO EAT UP THE REST OF THE INPUT LINE

FLUSH:	TLZ	F,(FL.EOL!FL.RSC) ;CLEAR SCANNER FLAGS
	TLNE	F,(FL.ETX)	;REACHED END OF LINE YET
	POPJ	P,		;YES, RETURN
	PUSHJ	P,GETONE	;GET A CHARACTER
	  JFCL			;IGNORE VARIOUS RETURNS
	  JFCL			;...
	JRST	FLUSH		;NOW LOOK FOR END OF LINE

;SUBROUTINE TO ENSURE THAT NO GARBAGE FOLLOWS LAST ARGUMENT OF A COMMAND
;CALLED BY VARIOUS COMMAND PROCESSORS AFTER READING LAST ARGUMENT BUT BEFORE
;	EXECUTING THE COMMAND ITSELF.
;RTNS:	CPOPJ	JUNK AFTER COMMAND
;	CPOPJ1	NOTHING BUT END OF LINE

CMDEND:	TLO	F,(FL.RSC)	;GET LAST ARGUMENT TERMINATOR
CMDE.1:	PUSHJ	P,GETONE	;GET A CHARACTER
	  JRST	CMDE.2		;SPECIAL, CHECK IT OUT
	  POPJ	P,		;NUMBER, JUNK
	  POPJ	P,		;SPECIAL, JUNK
CMDE.2:	CAIN	CH," "		;SPACE AFTER COMMAND
	JRST	CMDE.1		;ALLOW SPACES BEFORE ANY COMMENTS
	TLNE	F,(FL.EOL)	;END OF LINE
	AOS	(P)		;YES, NO JUNK
	POPJ	P,		;RETURN

;SUBROUTINE TO GET A SIXBIT WORD FROM THE INPUT STREAM INTO "T1"
;	ALSO RETURNS MASK FOR POSSIBLE COMMAND IN "T2"
;CLOBBERS T3

GETSIX:	MOVE	T3,[POINT 6,T1]	;PRIME THE BYTE POINTER
	SETZ	T1,		;AND THE RECEIVING WORD
	SETO	T2,		;AND THE EVENTUAL COMMAND MASK
	TLO	F,(FL.RSC)	;START WITH LAST TERMINATOR
GETS.1:	PUSHJ	P,GETONE	;GET A CHARACTER
	  JRST	GETS.2		;SPECIAL, GO LOOK
	  JRST	[JUMPE T1,CPOPJ	;NUMBERS CANNOT BE THE FIRST IN A COMMAND
		JRST .+1]	;BUT CAN BE PARTS OF IT (e.g. CPU0, RPE4)
	SUBI	CH,40		;TO SIXBIT
	TLNE	T3,770000	;GOT THEM ALL YET
	IDPB	CH,T3		;NO, INSERT NEW CHARACTER
	LSH	T2,-6		;ADJUST MASK FOR NEW CHARACTER
	JRST	GETS.1		;AND GET ANOTHER
GETS.2:	CAIN	CH," "		;STOP ON A BLANK
	JUMPE	T1,GETS.1	;YES, IGNORE LEADING BLANKS
	POPJ	P,		;RETURN WITH T1,T2 SET UP
;SUBROUTINE TO GET A NUMERIC ARGUMENT FROM THE INPUT STREAM INTO "T1"
;RTNS:	T1 .LT. 0 IF NO DIGITS FOUND
;CLOBBERS T2,T3

GETNUM:	SKIPA	T2,[^D10]	;DEFAULT RADIX
GETNUO:	MOVEI	T2,^D8		;HERE FOR OCTAL INPUT
	SETO	T1,		;NO DIGITS SEEN YET
	TLO	F,(FL.RSC)	;START WITH LAST TERMINATOR
GETN.1:	PUSHJ	P,GETONE	;GET A CHARACTER
	  JRST	GETN.2		;A SPECIAL, CHECK IT OUT
	  SKIPA			;A NUMBER, INCLUDE IT
	  JRST	GETN.3		;A LETTER, CHECK FOR K OR P
	MOVEI	T3,-"0"(CH)	;CONVERT TO ASCII
	CAIL	T3,(T2)		;RADIX CHECK
	JRST	GETN.4		;ILLEGAL ( NO 8'S OR 9'S IN OCTAL )
	SKIPGE	T1		;ANY DIGITS SO FAR
	TDZA	T1,T1		;NO, THIS IS THE FIRST
	IMULI	T1,(T2)		;"SHIFT" PREVIOUS SUM
	ADDI	T1,(T3)		;AND INCLUDE THE NEW DIGIT
	JRST	GETN.1		;GET MORE
GETN.2:	CAIN	CH,"#"		;INPUTTING OCTAL
	JRST	[JUMPGE T1,GETN.4 ;CAN'T CHANGE RADIX IN THE MIDDLE OF THE STREAM
		CAIN T2,^D8	;ALREADY DONE THIS ONCE
		POPJ P,		;YES, CAN'T TYPE TWO OF THEM
		MOVEI T2,^D8	;NEW RADIX
		JRST GETN.1]	;AND GET ANOTHER DIGIT
	CAIN	CH," "		;A BLANK
	JUMPL	T1,GETN.1	;YES, IGNORE LEADING BLANKS ALWAYS
	POPJ	P,		;STOP ON A SPECIAL OR OTHER BLANKS
GETN.3:	JUMPL	T1,CPOPJ	;ERROR IF NO DIGITS YET
	SETO	T3,		;FLAG INVALID LETTER
	CAIN	CH,"K"		;ALLOW "K"
	MOVEI	T3,^D10		;*1024 IF "K"
	CAIN	CH,"P"		;ALLOW "P"
	MOVEI	T3,^D9		;*512 IF "P"
	JUMPL	T3,GETN.4	;ILLEGAL IF NEITHER
	LSH	T1,(T3)		;ADJUST APPROPRIATELY
	SETZM	SAVCHR		;EAT UP THE "P" OR "K"
	POPJ	P,		;RETURN WITH NUMBER IN T1

GETN.4:	SETO	T1,		;ANYTHING ILLEGAL, RETURN -1
	POPJ	P,		;RETURN
;SUBROUTINE TO SET UP OPEN/LOOKUP BLOCKS WITH FILE NAME ENTERED

GETFN:	SETZB	T1,OPNBLK+1	;CLEAR STRUCTURE
	MOVSI	T2,'EXE'	;EXTENSION DEFAULT
	DMOVEM	T1,LUKBLK	;CLEAR FILE NAME, SET EXTENSION
	SETZ	T2,		;ANOTHER 0
	DMOVEM	T1,LUKBLK+2	;CLEAR REST OF SHORT LOOKUP BLOCK
GETF.1:	PUSHJ	P,GETSIX	;GET NEXT ARGUMENT
	JUMPE	T1,GETF.2	;NO MORE, LOOK FOR ERRORS
	CAIN	CH,":"		;DEVICE TERMINATOR
	JRST	[SKIPE OPNBLK+1	;ALREADY HAVE A DEVICE NAME
		 JRST BADFMT	;YES, SAY ILLEGAL CONSTRUCTION
		 MOVEM T1,OPNBLK+1 ;STORE IT
		 SETZM SAVCHR	;EAT UP THE COLON
		 JRST GETF.1]	;AND GET NEXT FIELD
	MOVEM	T1,LUKBLK	;STORE FILE NAME (MUST BE ONE)
	TLNE	F,(FL.EOL)	;END OF LINE SEEN
	JRST	GETF.2		;YES, CHECK RESULTS
	CAIE	CH,"["		;ONLY PPN SPEC CAN BE LEFT
	JRST	CPOPJ1		;RETURN NOW, GIVE RIGHT ERROR MESSAGE
	SETZM	SAVCHR		;EAT THE "["
	PUSHJ	P,GETNUO	;GET OCTAL PROJECT NUMBER
	TLNN	T1,-1		;SMALL NUMBERS ONLY
	CAIE	CH,","		;BETTER BE
	JRST	BADFMT		;ILLEGAL
	HRRE	T1,T1		;EXTEND SIGN
	JUMPLE	T1,BADFMT	;THIS IS BAD TOO
	HRLM	T1,LUKBLK+3	;STORE IT
	SETZM	SAVCHR		;EAT THE COMMA
	PUSHJ	P,GETNUO	;GET THE PROJECT NUMBER
	TLNE	T1,-1		;SMALL HERE TOO
	JRST	BADFMT		;NO GOOD
	JUMPLE	T1,BADFMT	;THIS IS REAL BAD
	HRRM	T1,LUKBLK+3	;STORE THAT
	CAIN	CH,"]"		;ALLOW CLOSURE
	SETZM	SAVCHR		;BUT DON'T REQUIRE IT
GETF.2:	MOVSI	T1,'DSK'	;DEFAULT DEVICE
	SKIPN	OPNBLK+1	;UNLESS STR GIVEN
	MOVEM	T1,OPNBLK+1	;ISN'T, FILL IT IN
	SKIPN	LUKBLK		;GOTTA HAVE A FILE NAME
	JRST	NOARGS		;COMPLAIN
	JRST	CPOPJ1		;RETURN
	SUBTTL	Some Output Subroutines

;SUBROUTINE TO OUTPUT SIXBIT VALUE IN AC "T1"

SIXOUA:	SKIPA	T2,@UA		;LUUO, GET SIXBIT VALUE
SIXOUT:	MOVE	T2,T1		;COPY SIXBIT OVER
SIXOU1:	JUMPE	T2,CPOPJ	;ALL DONE AT END OF SIXBIT WORD
	SETZ	T1,		;CLEAR RECEIVING AC
	LSHC	T1,6		;BRING IN A CHARACTER
	MOVEI	T1," "(T1)	;TO ASCII
	OUTCHR	T1		;OUTPUT IT
	JRST	SIXOU1		;AND GET THEM ALL

;SUBROUTINE TO OUTPUT "T1" IN CORRECT RADIX

DECOU2:	CAIGE	T1,^D10		;2 DIGIT MINIMUM
	OUTCHR	["0"]		;OUTPUT LEADING ZERO
	JRST	DECOUT		;NOW OUTPUT DECIMAL NUMBER
DECOUA:	SKIPA	T1,@UA		;LUUO, GET NUMBER
OCTOUA:	SKIPA	T1,@UA		;LUUO, GET NUMBER
DECOUT:	SKIPA	T3,[^D10]	;GET RADIX
OCTOUT:	MOVEI	T3,10		;GET RADIX
	JUMPL	T1,[OUTCHR ["-"] ;NEGATIVE VALUE
		    MOVMS T1	 ;OUTPUT "-" AND POSITIVE NUMBER
		    JRST OCTOU1] ;RESUME INLINE
OCTOU1:	IDIVI	T1,(T3)		;STRIP DIGIT
	PUSH	P,T2		;SAVE IT
	SKIPE	T1		;WAS THAT ALL
	PUSHJ	P,OCTOU1	;NO, GET ANOTHER
	POP	P,T1		;RESTORE CHARACTER
	MOVEI	T1,"0"(T1)	;TO ASCII
	OUTCHR	T1		;OUTPUT IT
	POPJ	P,		;AND RETURN

;SUBROUTINE TO OUTPUT "T1" AS ASCII WORD

ASCOUT:	SETZ	T2,		;MAKE SURE THERE'S A NULL AT THE END
	OUTSTR	T1		;OUTPUT T1 AND MAYBE T2
	POPJ	P,		;RETURN

;SUBROUTINE TO OUTPUT FREE CORE NUMBERS AC A PERCENTAGE

PERCNT:	SKIPGE	T1,FRUSED	;GET AMOUNT TAKEN
	OUTCHR	["-"]		;NEGATIVE, OUTPUT MINUS
	MOVMS	T1		;MAKE POSITIVE NUMBER
	IMULI	T1,^D10000	;SCALE
	IDIV	T1,FREAVB	;COMPUTE PERCENTAGE
	IDIVI	T1,^D100	;UN-SCALE
	IDIVI	T2,^D10		;AND 2 HUNDREDTHS DIGITS
	FORMAT	<,<DEC T1>,<.>,<DEC T2>,,<DEC T3>,<%>>
	POPJ	P,		;AND RETURN
	SUBTTL	Some Random (or stolen) Subroutines

;SUBROUTINE TO RETURN "FREE" CORE
;ENTER GIVWDS: T1=# WDS. TO RETURN, T2=START ADR. OF CORE

GIVWDS:	ADDI	T1,3		;CONVERT TO # 4WD. BLOCKS
	ASH	T1,-2
	SUB	T2,LOCORE	;GET ADR. RELATIVE TO START OF TABLE
	MOVN	T3,T1
	ADDM	T3,FRUSED	;DECREMENT FREE-CORE USED
	ADDM	T1,FRERTN	;INCREMENT AMOUNT RETURNED
	LSH	T2,-2		;/4 TO CONVERT TO BITS
	IDIVI	T2,^D36		;COMPUTE WORD LOC, STARTING BIT
	HRLS	T2		;WORD POSITION IN BOTH HALVES
	ADD	T2,FREPTR	;SET AOBJN WORD FOR TABLE
				;FALL INTO SETZRS

;SUBROUTINE TO SET ZEROS IN A TABLE
;ARG	T1=HOW MANY BITS TO CLEAR
;	T2=AOBJN POINTER FOR TABLE
;	T3=POSITION IN WORD OF FIRST BIT TO CLEAR
;	(0=BIT 0, 1=BIT 1, ETC.)

SETZRS:	EXCH	T1,T3		;SET ACS FOR CLRBTS
	MOVEI	T4,^D36		;ADJUST FOR 1ST WORD
	SUBM	T4,T1
	HRRZ	T4,T2		;SET T4 FOR CLRBTS
	PUSH	P,T2		;SAVE AOBJN WORD
	PUSHJ	P,CLRBTS	;CLEAR SOME BITS
	  HALT	.		;STOPCD BAC HERE
	POP	P,T2		;RESTORE AOBJN WORD
	HLRE	T3,T2		;LENGTH OF POINTER
	SUB	T2,T3		;COMPUTE TOP OF TABLE
	CAILE	T4,(T2)		;FINAL ADR PAST TOP?
	HALT	.		;STOPCD PTT HERE
	POPJ	P,		;NO, GOOD RETURN
;SUBROUTINE TO SET UP A BIT MASK FOR IORM OR ANDCAM INTO A TABLE
;ENTER WITH T1=POSITION (36=BIT0, 1=BIT35) AND T3=HOW MANY
;AFTER THE FIRST CALL USE BITMS2, T3=COUNT RETURNS T1=MASK,
;T3=REMAINING COUNT ROUTINE HAS RETURNED FINAL MASK IF
;T3 .LE. 0 ASSUMES T4=ADR IN TABLE, BITMS2 INCREMENTS T4

BITMSK:	PUSH	P,T1		;SAVE POSITION
	MOVN	T1,T3		;- COUNT
	CAILE	T3,^D36		;MORE THAN 1 WORD?
	MOVNI	T1,^D36		;YES, SETTLE FOR A WORD (OR LESS)
	MOVSI	T2,400000	;SET TO PROPOGATE A MASK
	ASH	T2,1(T1)	;GET THE RIGHT NUMBER OF BITS
	SETZ	T1,
	LSHC	T1,@0(P)	;POSITION THE BITS IN T1 (=MASK)
	SUB	T3,0(P)		;REDUCE THE COUNT TO THE NEW VALUE
	POP	P,T2		;RESTORE T2
	POPJ	P,		;RETURN

;HERE AFTER FIRST CALL, MASK STARTS AT BIT 0

BITMS2:	SETO	T1,		;MASK STARTS AT BIT 0
	MOVNI	T2,-^D36(T3)	;SET UP SHIFT
	CAIGE	T3,^D36		;DONT SHIFT IS .GE. 36
	LSH	T1,(T2)		;POSTION THE MASK
	SUBI	T3,^D36		;REDUCE THE COUNT
	AOJA	T4,CPOPJ	;UPDATE THE POSITION AND RETURN

;ROUTINE TO CLEAR BITS FROM A TABLE
;ENTER T1=POSITION, T3=COUNT, T4=TABLE ADR (POSITION=36 IF BIT0, 1 IF BIT35)
;RETURNS POPJ IF BIT ALREADY 0, POPJ1 OTHERWISE

CLRBTS:	PUSHJ	P,BITMSK	;GENERATE A MASK
CLRBT1:	MOVE	T2,MONITR(T4)	;WORD TO CLEAR BITS FROM
	TDC	T2,T1		;ARE THE BITS ALREADY OFF?
	TDNE	T2,T1
	POPJ	P,		;YES, RETURN NON-SKIP
	MOVEM	T2,MONITR(T4)	;NO, NOW THEY ARE
	JUMPLE	T3,CPOPJ1	;DONE IF COUNT .LE. 0
	PUSHJ	P,BITMS2	;GENERATE MASK FOR NEXT WORD
	JRST	CLRBT1		;AND GO CLEAR THOSE BITS
;SUBROUTINE TO PERFORM GETTAB VIA SPY IF POSSIBLE
;ARGS	T1=GETTAB ARG
;VALUES	T1=GETTAB VALUE

GTBSPY:	SKIPGE	T1		;WANT JOB NUMBER (- INDEX)
	HRLI	T1,(J)		;YES, INSERT IT
	SKIPN	NUMTAB		;HAVE GETTAB STUFF YET
	JRST	[GETTAB T1,	;NO, GET IT FROM CURENT MONITOR
		   POPJ P,	;IT FAILED
		 JRST CPOPJ1]	;GIVE GOOD RETURN
	PUSH	P,P1		;SAVE P REGS
	PUSH	P,P2		;...
	PUSH	P,P3		;...
	HRRZI	P1,(T1)		;P1=TABLE NUMBER
	ADD	P1,NUMTAB	;ADDR OF PTR FOR THIS TABLE
	LDB	P3,[POINT 3,MONITR(P1),11] ;GET TYPE OF TABLE
	CAIN	P3,.SLIXP	;IS DATUM IN THE PDB?
	JRST	GTBPDB		;YES, GO GET IT
	CAIN	P3,.SLIXS	;INDEXED BY JOB OR SEGMENT NUMBER?
	SKIPA	P2,JBTMXL	;YES, MAX IS JOBN+SEGN-1
	LDB	P2,[POINT 9,MONITR(P1),8] ;NO. GET MAX ITEM VALUE
	CAIE	P3,.SLIXR	;IS THIS A RANGED GETTAB?
	JRST	GTBSP1		;NO, P2 CONTAINS 0,,MAX
	SKIPN	P3,RNGTAB	;DO WE HAVE THE ADDRESS OF RNGTAB?
	JRST	GTBSP3		;NO, FAIL
	ADDI	P2,(P3)		;ADD OFFSET INTO RNGTAB FOR THIS ENTRY
	MOVE	P2,MONITR(P2)	;GET MIN,,MAX FROM RNGTAB ENTRY
GTBSP1:	HLRZ	P3,T1		;GET ITEM NUMBER CALLER WANTS
	CAILE	P3,(P2)		;.LE. MAX?
	JRST	GTBSP3		;NO, FAIL
	MOVSS	P2		;EXCHANGE MIN AND MAX
	CAIGE	P3,(P2)		;AND .GE. MIN?
	JRST	GTBSP3		;NO, FAIL
	HRRZ	T1,MONITR(P1)	;GET BASE OF TABLE WANTED
	ADD	T1,P3		;PLUS INDEX WANTED
	CAMGE	T1,LOWLIM	;IN HIGH SEG?
	SKIPA	T1,MONITR(T1)	;GET DATA ITEM
	PUSHJ	P,WDFTCH	;YES, GET IT
GTBSP2:	AOS	-3(P)		;GIVE GOOD RETURN
GTBSP3:	POP	P,P3		;RESTORE P REGS
	POP	P,P2		;...
	POP	P,P1		;...
	POPJ	P,		;RETURN

GTBPDB:	SKIPN	PDBPTR		;IS JBTPDB BASE AVAILABLE?
	JRST	GTBSP3		;NO, FAIL
	HLRZS	T1		;JOB NUMBER
	ADD	T1,PDBPTR	;PLUS JBTPDB ADDRESS
	HRRZ	T1,MONITR(T1)	;GET ADDRESS OF WD 0 OF JOBS PDB
	JUMPE	T1,GTBSP2	;NO JOB THERE, RETURN 0
	ADD	T1,MONITR(P1)	;ADD ON ITEM NUMBER
	MOVE	T1,MONITR(T1)	;GET THE WORD FROM THE PDB
	JRST	GTBSP2		;GIVE GOOD RETURN
;SUBROUTINE TO RETURN THE CONTENTS OF PAGTAB FOR A SPECIFIC PAGE
;ARGS	P1 = PAGE NUMBER
;RETURN T1 = BITS FROM PAGTAB

PGFTCH:	CAML	P1,PGTLEN	;RANGE CHECK IT
	JRST	[MOVSI T1,PT.NXM ;OUT OF RANGE, SAY NXM
		 POPJ P,]	;AND RETURN
	MOVE	T1,P1		;COPY PAGE NUMBER
	ADD	T1,PTBADR	;ADD ADDRESS OF PAGTAB
;	JRST	WDFTCH		;FALL INTO WORD FETCH ROUTINE

;SUBROUTINE TO FETCH A SPECIFIC WORD FROM THE MONITOR HIGH SEGMENT
;ARGS	T1 = ADDRESS (1B0 ON IF WANT PHYSICAL 22 BIT ADDRESS)
;RETURN T1 = THE CONTENTS

WDFTCH:	SKIPN	EXEDIR		;RUNNING FROM AN EXE FILE
	JRST	[MOVE T2,[PEEK T1,] ;NO, GET IT FROM RUNNING MONITOR
		 TLZE T1,(1B0)	;WANT PHYSICAL ADDRESS
		 TRO T2,UU.PHY	;YES, DO PHYSICAL ONLY PEEK
		 XCT T2		;GET THE WORD
		 POPJ P,]	;AND RETURN
	TLZE	T1,(1B0)	;WANT PHYSICAL WORD
	JRST	[IDIVI T1,1000	;SPLIT INTO PAGE AND OFFSET INTO PAGE
		 JRST WDFPHY]	;AND BYPASS EPT RELOCATION
	CAMGE	T1,LOWLIM	;IN LOW MONITOR LOW SEGMENT?
	JRST	[MOVE T1,MONITR(T1) ;YES, ALREADY HAVE THAT SOMEWHERE
		 POPJ P,]	;RETURN
	IDIVI	T1,1000		;SPLIT INTO PAGE AND OFFSET INTO PAGE
	LDB	T3,[POINT 9,T1,26] ;GET SECTION NUMBER
	ANDI	T1,777		;KEEP JUST IN-SECTION PAGE
	CAILE	T3,1		;SECTION 0 AND 1 ARE EASY
	JRST	[ADD	T3,EPTADR ;FOR OTHERS, MUST LOOK IN SECTAB
		 HRRZ	T3,MONITR+540(T3) ;GET SECTAB ENTRY
		 LSH	T3,9	;CONVERT TO ADDRESS OF SECTION MAP
		 ADD	T1,T3	;OFFSET IN SECTION MAP FOR OUR ADDRESS
		 TLO	T1,(1B0) ;PHYSICAL REFERENCE
		 PUSH	P,T2	;SAVE OFFSET
		 PUSHJ	P,WDFTCH ;RECURSE
		 TLZ	T1,-1	;CLEAR MAP BITS
		 POP	P,T2	;RESTORE OFFSET
		 JRST	WDFPHY]	;CONTINUE
	ADD	T1,EPMADR	;RELOCATE INTO THE EXEC MAP
	LDB	T1,[POINT 13,MONITR(T1),35] ;GET PAGE NUMBER
WDFPHY:	HRRZ	T3,EXEDIR	;NUMBER OF WORDS IN EXE DIRECTORY
	MOVNI	T3,-1(T3)	;DON'T COUNT HEADER WORD
	HRLZS	T3		;FORM AOBJN
WDFT.1:	HRRZ	T4,EXEDIR+2(T3)	;GET CORE ADDRESS FROM DESCRIPTOR
	CAILE	T4,(T1)		;PAST THE ONE WE WANT
	HALT	.		;WORD NOT IN FILE
	LDB	T5,[POINT 9,EXEDIR+2(T3),8] ;GET REPEATER
	ADDI	T5,1(T4)	;FIRST PAGE NOT IN POINTER
	CAIL	T1,(T5)		;PAGE IN THIS POINTER AT ALL
	JRST	[ADD T3,[1,,1]	;ADJUST FOR DOUBLE WORD ENTRIES
		 AOBJN T3,WDFT.1 ;GET ANOTHER POINTER
		 HALT .]	;WORD NOT IN FILE
	SUBI	T1,(T4)		;HOW FAR INTO POINTER
	ADD	T1,EXEDIR+1(T3)	;HOW FAR INTO THE FILE PROPER
	TLZ	T1,-1		;KEEP IT REASONABLE (FLAG BITS)
	LSH	T1,^D9		;CONVERT TO A PAGE NUMBER IN THE FILE
	ADDI	T1,(T2)		;INCLUDE WORD OFFSET NOW
	IDIVI	T1,DSKBLK	;NOW CONVERT TO BLOCK NUMBER AND OFFSET INTO BLOCK
	MOVSI	T3,-NBCSHE	;SEARCH FOR BLOCK IN IN-CORE CACHE
	HLRZ	T4,DCACHE(T3)	;BLOCK DESCRIBED IN CACHE
	CAIE	T4,(T1)		;IS THIS IT
	AOBJN	T3,.-2		;NO, KEEP LOOKING
	JUMPL	T3,WDFT.2	;FOUND ONE, UPDATE LEAST RECENTLY USED TABLES
	HRLM	T1,DCACHE+NBCSHE-1 ;STORE BLOCK NUMBER IN LAST (OLDEST)
	HRRZ	T3,DCACHE+NBCSHE-1 ;WHERE DATA IS TO BE READ
	SOS	T3		;-1 FOR THE IOWD
	HRLI	T3,-DSKBLK	;NUMBER OF WORDS
	SETZ	T4,		;LAST IOWD
	USETI	XPN,1(T1)	;POSITION FILE
	IN	XPN,T3		;READ BLOCK INTO CACHE
	 CAIA			;READ OK
	  HALT	.		;DISK I/O READ ERROR
	MOVEI	T3,NBCSHE-1	;INDEX WHERE FOUND (READ)
WDFT.2:	HRRZS	T3		;ISOLATE INDEX
	CAIG	T3,NBCSHE/3	;DON'T RIPPLE IF ALREADY CLOSE TO START OF TABLE
	JRST	WDFT.3		;THIS MIGHT NOT BE TOO GOOD WITH A SMALL "NBCSHE"
	PUSH	P,DCACHE(T3)	;SAVE ENTRY FOUND
	MOVE	T4,DCACHE-1(T3)	;COMPRESS TABLE SO LEAST USED IS LAST
	MOVEM	T4,DCACHE(T3)	;MOVE UP ENTRIES BELOW ONE FOUND
	SOJG	T3,.-2		;SO NEW ONE CAN BE FOUND QUICKLY
	POP	P,DCACHE(T3)	;PUT NEW ONE AT THE FRONT
WDFT.3:	HRRZ	T1,DCACHE(T3)	;GET ADDRESS OF DATA IN THIS BUFFER
	ADD	T1,T2		;PLUS OFFSET INTO BUFFER
	MOVE	T1,(T1)		;FETCH IT
	POPJ	P,		;AND RETURN
	SUBTTL	Local UUO Handler

UUOCON:	LDB	UU,[POINT 9,40,8] ;GET OPCODE
	HRRZ	UA,40		;GET EFFECTIVE ADDRESS
	CAILE	UU,UUOMAX	;RANGE CHECK
	HALT	.		;WHAT
	SKIPGE	UU,UUODSP-1(UU)	;FAST UUO (DOESN'T CLOBBER REGS)
	JRST	(UU)		;YES, GO RIGHT TO IT
	PUSH	P,T1		;SAVE ALL THE TEMP REGS
	PUSH	P,T2		;...
	PUSH	P,T3		;...
	PUSH	P,T4		;...
	PUSH	P,T5		;...
	PUSHJ	P,(UU)		;CALL ROUTINE
	POP	P,T5		;NOW UNDO ALL THAT
	POP	P,T4		;...
	POP	P,T3		;...
	POP	P,T2		;...
	POP	P,T1		;...
	POPJ	P,		;AND RETURN

UUODSP:	EXP	DECOUA		;001 - OUTPUT DECIMAL NUMBER
	EXP	OCTOUA		;002 - OUTPUT OCTAL NUMBER
	EXP	SIXOUA		;003 - OUTPUT SIXBIT VALUE
	EXP	PERCNT		;004 - FREE CORE STATS
	SETZ	CRPOPJ		;005 - OUTPUT A CRLF
	EXP	[MOVE T1,@UA	;006 - OUTPUT OCTAL NUMBER * 4
		 LSH T1,2
		 JRST OCTOUT]
	EXP	[JSP T2,GTTOUT	;007 - OUTPUT GETTAB VALUE AS OCTAL
		 EXP OCTOUT]
	EXP	[JSP T2,GTTOUT	;010 - OUTPUT GETTAB VALUE AS DECIMAL
		 EXP DECOUT]
	EXP	[JSP T2,GTTOUT	;011 - OUTPUT GETTAB VALUE AS ASCII WORD
		 EXP ASCOUT]
	EXP	[JSP T2,GTTOUT	;012 - OUTPUT GETTAB VALUE, DECIMAL, 2 DIGITS
		 EXP DECOU2]
UUOMAX==<.-UUODSP>		;HIGHEST LUUO

GTTOUT:	MOVE	T1,@UA		;GET GETTAB ARGUMENT
	PUSHJ	P,GTBSPY	;GET VALUE
	  HALT	.		;WHAT
	JRST	@0(T2)		;TO CORRECT OUTPUT ROUTINE
MONTAB:	ASCII	/Jan/
	ASCII	/Feb/
	ASCII	/Mar/
	ASCII	/Apr/
	ASCII	/May/
	ASCII	/Jun/
	ASCII	/Jul/
	ASCII	/Aug/
	ASCII	/Sep/
	ASCII	/Oct/
	ASCII	/Nov/
	ASCII	/Dec/

	XLIST			;FORCED OUT LITERAL POOL HERE
	LIT
	LIST
	.ENDPS			;END OF THE CODE PSECT
	END	FRECOR		;END OF THIS PROGRAM