Google
 

Trailing-Edge - PDP-10 Archives - tops10_tools_bb-fp64a-sb - 10,7/map/map.mac
There are 4 other files named map.mac in the archive. Click here to see a list.
;TITLE	MAP - DECsystem-10 page mapper
SUBTTL	D. P. Mastrovito /DPM


;COPYRIGHT (C) 1980,1981,1982,1983,1984,1985,1986 BY
;DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.
;
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.


; Version numbers
;
	MAPMAJ==2			;MAJOR VERSION
	MAPMIN==0			;MINOR VERSION
	MAPEDT==56			;EDIT NUMBER
	MAPWHO==0			;WHO DID IT
	%%MAP==<BYTE(3)MAPWHO(9)MAPMAJ(6)MAPMIN(18)MAPEDT>

	MAPDAY=="22"			;BUILD DAY
	MAPMON=="Dec"			;BUILD MONTH
	MAPYER=="85"			;BUILD YEAR


	SALL				;FOR CLEAN LISTINGS
	.DIRECT FLBLST			;FOR CLEANER LISTINGS
SUBTTL	Table of Contents


;		Table of Contents for MAP %2(35)
;
;
;			   Section			      Page
;   1. Table of contents. . . . . . . . . . . . . . . . . . .    2
;   2. Revision history . . . . . . . . . . . . . . . . . . .    3
;   3. Compiler interface setup . . . . . . . . . . . . . . .    5
;   4. Program interface definitions. . . . . . . . . . . . .    8
;   5. Internal definitions . . . . . . . . . . . . . . . . .    9
;   6. .MAPD - Deposit. . . . . . . . . . . . . . . . . . . .   11
;   7. .MAPE - Examine. . . . . . . . . . . . . . . . . . . .   12
;   8. .MAPG - GETTAB UUO simulation. . . . . . . . . . . . .   13
;   9. .MAPI - Initialization . . . . . . . . . . . . . . . .   18
;  10. .MAPJ - JOBPEK UUO simulation. . . . . . . . . . . . .   25
;  11. Address mapping
;       11.1.   Compute a mapped address. . . . . . . . . . .   27
;       11.2.   Convert virtual to physical addresses . . . .   28
;       11.3.   Copy a block of mapped data . . . . . . . . .   30
;       11.4.   KA relocation and protection. . . . . . . . .   31
;       11.5.   KI paging . . . . . . . . . . . . . . . . . .   32
;       11.6.   KL paging . . . . . . . . . . . . . . . . . .   33
;       11.7.   Dispatch tables . . . . . . . . . . . . . . .   35
;       11.8.   Monitor . . . . . . . . . . . . . . . . . . .   36
;       11.9.   Job . . . . . . . . . . . . . . . . . . . . .   38
;       11.10.  File. . . . . . . . . . . . . . . . . . . . .   40
;  12. Cache management
;       12.1.   Clear out the cache . . . . . . . . . . . . .   42
;       12.2.   Map the cache . . . . . . . . . . . . . . . .   43
;       12.3.   Set up the hash tables and links. . . . . . .   45
;       12.4.   Set cache size. . . . . . . . . . . . . . . .   46
;       12.5.   Allocate a chunk for the cache. . . . . . . .   47
;       12.6.   Deallocate a page from the cache. . . . . . .   48
;       12.7.   Find an entry in the cache. . . . . . . . . .   49
;       12.8.   Insert (replace) a new page in the cache. . .   50
;       12.9.   Move entry to top of list . . . . . . . . . .   51
;  13. Text I/O
;       13.1.   Character . . . . . . . . . . . . . . . . . .   52
;       13.2.   ASCIZ . . . . . . . . . . . . . . . . . . . .   53
;       13.3.   Sixbit. . . . . . . . . . . . . . . . . . . .   54
;       13.4.   Octal . . . . . . . . . . . . . . . . . . . .   55
;       13.5.   Filespec. . . . . . . . . . . . . . . . . . .   56
;       13.6.   Miscellaneous . . . . . . . . . . . . . . . .   57
;  14. Paging
;       14.1.   Check accessibility . . . . . . . . . . . . .   58
;       14.2.   Create/Destroy. . . . . . . . . . . . . . . .   59
;       14.3.   SPY page creation . . . . . . . . . . . . . .   60
;  15. File I/O
;       15.1.   Open a file . . . . . . . . . . . . . . . . .   61
;       15.2.   Close a file. . . . . . . . . . . . . . . . .   63
;       15.3.   Position a file . . . . . . . . . . . . . . .   64
;       15.4.   Input/Output. . . . . . . . . . . . . . . . .   65
;       15.5.   Scan a filespec . . . . . . . . . . . . . . .   66
;  16. EXE file routines
;       16.1.   Load and validate directory . . . . . . . . .   69
;       16.2.   Find a file page. . . . . . . . . . . . . . .   71
;       16.3.   Find a directory block. . . . . . . . . . . .   72
;  17. FORTRAN interface. . . . . . . . . . . . . . . . . . .   73
;  18. Context switch . . . . . . . . . . . . . . . . . . . .   74
;  19. Error handling . . . . . . . . . . . . . . . . . . . .   75
;  20. AC save routines . . . . . . . . . . . . . . . . . . .   82
;  21. Literals . . . . . . . . . . . . . . . . . . . . . . .   84
;  22. Data storage . . . . . . . . . . . . . . . . . . . . .   85
;  23. End. . . . . . . . . . . . . . . . . . . . . . . . . .   86
SUBTTL	Revision history


; 1	Creation. Map virtual monitor addresses.
;
; 2	Map physical monitor addresses.
;
; 3	Add job mapping.
;
; 4	Start adding code for file mapping.
;
; 5	Change calling conventions to always use a single AC. Add
;	FORTRAN interface.
;
; 6	More work on file mapping.  Accept ASCIZ filespecs.
;
; 7	Handle multiple directory page EXE files.
;
; 10	Implement new page caching routines.
;
; 11	Add TITLE. macro.
;
; 12	Shuffle lots of code into a more logical organization.  Start
;	to clean up initialization code.
;
; 13	Begin adding intelligent error handling.
;
; 14	Edit 10 broke file mapping badly.  Make it work again.  Remove
;	all references to AC 'I' as well as the old paralell mapping
;	tables.
;
; 15	Finally add code to handle GETTAB immediate of the range table.
;
; 16	Add support for pathological names.
;
; 17	Attempt to close off old channel from previous call early
;	in the .MAPI routine.
;
; 20	Rewrite the FORTRAN interface.  /WSM
;
; 21	Finish adding error handling for all non-I/O errors.
;
; 22	Store the CPU and paging type in the data block.
;
; 23	Add support for KL paging shared and indirect pointers.
;
; 24	Avoid an extra GETTAB simulation by reading low core location 22
;	to get paging type and APR serial number.  Then convert serial
;	number to CPU type.  Always use physical addressing when looking
;	at low core.
;
; 25	Redefine all FL.??? and FR.??? flags as 18 bit quantities.  Fix
;	bug in testing for physical pages that caused CSHFND to never
;	find a page in the cache sometimes.  Add AC save co-routines.
; 26	Remove .MPCOR mapping code and add code to handle virtual vs.
;	physical memory addressing correctly.  If the first 112K of the
;	monitor is mapped one for one virtual to physical, remember this
;	so subsequent address calculations can bypass expensive exec
;	page mapping code.
;
; 27	Enhance the FORTRAN interface again by making it type out errors
;	if the caller doesn't setup a return address.  /WSM
;
; 30	Don't terminate text blocks with a NUL.  This confuses FORTRAN.
;	Zero the blocks instead.  Don't use the caller's stack, set up
;	an internal one.  Invent a flag word in the data block which is
;	non-zero if SPYing.  Add flag MP.SPY to require SPYing if so
;	requested.  Remove the 20 page restriction on cache size.  The
;	sky's the limit or CORMAX (which ever comes first).  Return the
;	sixbit prefix so a superior program can do intelligent things.
;
; 31	Add support for reading funny space.  Also fix bugs associated
;	with KL paging indirect pointers.
;
; 32	GETTAB values for start and end of funny space, and the highest
;	unmapped exec address.  Remove code to compute these values and
;	associated flags.
;
; 33	Speed up JOBPEK simulation by doing either a MOVE and MOVEM,
;	DMOVE and DMOVEM, or a BLT to transfer data from mapped pages
;	to user pages.  Remove COUNT. macro.
;
; 34	Fix up filespec defaulting and better handle sixbit PPNs.
;	Remove last references to ACs P1 and P2.
;
; 35	Incorporate the FORTRAN INCLUDE file in the MACRO sources.
;
; 36	Make hardware KI paging work.  It's about time!
;
; 37	Make use of new FILOP. function to return the filespec of crash file.
;
; 40	Speed up initialization by a factor of two.
;
; 41	Edit 15 didn't quite make it.  Teach OCTOUT about negative numbers.
;	Type negative GETTAB tables as -n.
;
; 42	Rework GTBINI extensively by removing old BOOTWD hack to determine
;	the CPU and paging type.  Use the Exec Data Vector if we can.
;
; 43	Rewrite the TITLE. macro, add build string for WSM.  Add symbolic
;	offsets for initialization block.  Add routine .MAPC to clear
;	out the mapper statistics block.  Don't set a PATH. block pointer
;	if there's no directory (default [-] correctly).
;
; 44	Add crock to check for monitor's high segment being mapped.  This
;	will allow GETTABs of values in the high segment to work on unrun
;	monitors.
;
; 45	In file mode, get the returned filespec with one FILOP. UUO, not
;	two.  Replace MPIFF% (Initialization Failed for File mapping) with
;	a the more general code MPMIP% (Mapper Initialization failure).
;
; 46	Add .MAPI argument .MPDSN to specify the default section number to
;	use if an address of 400000,,n is given.  This will normally be set
;	to zero to things don't break.  Also, add an internal argument block
;	so programs have to assemble in the argument block length.
;
; 47	Include cosmetic improvements and KL paging patch supplied by
;	Joe Smith of the Colorado School of Mines.  The KL paging stuff
;	fixes an old WHO bug that caused address calculations to fail while
;	trying to examine non-zero section addresses in a crash file.
;
; 50	Add copyrights to .MAC, .REL, and .FOR files.
;
; MAP %2(50) released with 7.02
;
; 51	Add counter .MPJPU to tally up the number of JOBPEK UUOs executed.
;
; 52	Remove references to PAGADR.  It's not needed.
;
; 53	During GETTAB initialization, if the highest unmapped exec address
;	is known, use it instead of defaulting it to DEFUEA.
;
; 54	Correct FORTRAN definition of .MPJPU (JOBPEK UUOs executed).
;
; 55	Fix typo in error message.  Update copyrights.
;
; 56	(RDH) Fix to handle extended/PSECTed monitors - use %CNSUP system
;	uptime as "mapped" flag for .EXE files.
SUBTTL	Macros


; Macros to accumulate text
;
DEFINE	INIT.	(ARG),<

DEFINE	ARG'..	(TEXT),<
	DEFINE	APPND.	(X,Y,Z),<ARG'..	(<TEXT''X'Y'Z>)>
	DEFINE	ARG'.,<TEXT>
> ;END ARG'..

	ARG'..

> ;END INIT.


; Macro to build a byte pointer to a masked quantity
;
DEFINE	POINTR	(A,M),<POINT <^L<-<<M>_<^L<M>>>-1>>,A,<<^L<<M>&<-<M>>>>>>


; Macro to generate calls to the error handler
;
DEFINE	ERR.	(COD,RET),<
	PUSHJ	P,[PUSHJ P,ERROR
		   IFNB <COD>,<MP'COD'%>,,RET]
>


; Macro to generate mapping error table entries
;
DEFINE	MERR.	(SYM,TXT),<
	.XCREF	...ERR, MP'SYM'%
	...ERR==...ERR+1
	MP'SYM'%==:...ERR
	''SYM'',,[ASCIZ |TXT|]
>
; Macro to generate a TITLE, build, and version text
;
DEFINE	TITLE.	(NAM,ABV,TXT),<
	MN1==<ABV'MIN/^D26>
	IFE MN1,<MN2==ABV'MIN>
	IFG MN1,<MN2=ABV'MIN-<^D26*MN1>>
	IFE ABV'MIN-^D26,<MN2==<ABV'MIN+<MN1==0>>>
	IFE ABV'MIN-^D52,<MN2==<<^D26-1>+<MN1==1>>>
	IFN MN1,<MN1==MN1+"@">
	IFN MN2,<MN2==MN2+"@">
	MNV==<<MN1_7>!MN2>

;; Generate TITLE
	INIT.	(TTL)
	APPND.	(<TITLE	'NAM %>,\ABV'MAJ,)
	IFN MNV,<APPND. (,\"MNV,)>
	APPND.	(<(>,\ABV'EDT,<)>)
	IFN ABV'WHO,<APPND. (<->,\ABV'WHO,)>
	APPND.	(< >,'TXT,)
	TTL.

;; Generate PRINTX
	INIT.	(PTX)
	APPND.	(<PRINTX ['NAM %>,\ABV'MAJ,)
	IFN MNV,<APPND. (,\"MNV,)>
	APPND.	(<(>,\ABV'EDT,<)>)
	IFN ABV'WHO,<APPND. (<->,\ABV'WHO,)>
	APPND.	(< >,'TXT,)
	IFN FTFORTRAN,<APPND. (< FORTRAN interface>,,)>
	appnd.	(<]>,,)
	IF2,<PTX.>

;; Generate build date
	INIT.	(BLD)
	APPND.	(<ASCIZ	|'NAM version >,\ABV'MAJ,)
	IFN MNV,<APPND. (,\"MNV,)>
	APPND.	(<(>,\ABV'EDT,<)>)
	IFN ABV'WHO,<APPND. (<->,\ABV'WHO,)>
	APPND.	(< built on >,\"ABV'DAY,<->)
	APPND.	(\"ABV'MON,<->,\"ABV'YER)
	APPND.	(<|>,,)

;; Generate program version
	INIT.	(VER)
	APPND.	(<ASCIZ	|'NAM %>,\ABV'MAJ,)
	IFN MNV,<APPND. (,\"MNV,)>
	APPND.	(<(>,\ABV'EDT,<)>)
	IFN ABV'WHO,<APPND. (<->,\ABV'WHO,)>
	APPND.	(<|>,,)


;; Generate copyright text
	INIT.	(CPY)
IFE COMPILER,<
	APPND.	(<ASCIZ |>,\"15,\"12)
	APPND.	(<'NAM %>,\ABV'MAJ,)
	IFN MNV,<APPND. (,\"MNV,)>
	APPND.	(<(>,\ABV'EDT,<)>)
	IFN ABV'WHO,<APPND. (<->,\ABV'WHO,)>
	APPND.	(< 'TXT>,\"15,\"12)
>
IFN COMPILER,<
	APPND.	(<ASCIZ |>,,)
>
	APPND.	(<COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION >,,)
	APPND.	(<1980,1986.  ALL RIGHTS RESERVED.>,,)
	APPND.	(\"15,\"12,<|>)

>
	TITLE.	(MAP,MAP,<DECsystem-10 page mapper>)
DEFINE	STR	(TEXT),<IFN COMPILER,<ASCIZ |TEXT|>>
DEFINE	CRLF,<IFN COMPILER,<BYTE(7)15,12>>

DEFINE	BLK%	(MAC,FOR,WDS),<
	MAC==:<FOR==:OFFSET>
		CRLF
		STR	<	PARAMETER 'FOR = ">
		STR	(\OFFSET)
	OFFSET==OFFSET+WDS
> ;END DEFINE BLK%

DEFINE	SYM%	(MAC,FOR,VAL),<
	IFDIF <None><MAC>,<MAC==:VAL>
	IFDIF <None><FOR>,<
		CRLF
		STR	<	PARAMETER 'FOR = "'VAL>
	> ;END IFDIF
> ;END DEFINE SYM%
SUBTTL	MACRO-10/compiler interface setup


	OFF==0				;TURNS A FEATURE TEST OFF
	ON==1				;TURNS A FEATURE TEST ON
	COMPILER==0			;INITIALLY NO COMPILER CODE
	HGHORG==400000			;HIGH SEGMENT ORIGIN


DEFINE	FT	(FTS,VAL),<
IFNDEF FT'FTS,FT'FTS==VAL		;;SET DEFAULT VALUE
IFN FT'FTS,<FT'FTS==FT'FTS&1>		;;NORMALIZE SETTING
COMPILER==COMPILER+<IFN FT'FTS,<1>>	;;MAYBE TURN ON COMPILER CODE
> ;END DEFINE FT

	FT	FORTRAN,OFF		;FORTRAN INTERFACE


IFG COMPILER-1,<
	PRINTX ? Multiple interfaces selected
	PASS2
	END
>

IFE COMPILER,<
	SEARCH	UUOSYM			;FOR TOPS-10 UUO SYMBOLS

	TWOSEG				;MAKE US SHARABLE
	RELOC	HGHORG			;START LOADING HERE

.MAP::	ENTRY	.MAP,.MAPI,MAPI		;LOAD IF LIBRARY SEARCH

COPYRI:	CPY.				;GENERATE COPYRIGHT TEXT
BUILD:	BLD.				;GENERATE BUILD TEXT
VERSIO:	VER.				;GENERATE VERSION TEXT

> ;END IFE COMPILER

IFN COMPILER,<RIM10>
SUBTTL	Program interface definitions


	STR	<
!		>
IFN COMPILER,<VER.>
	STR	<
!              Definitions for the FORTRAN interface
!
!>
IFN COMPILER,<CPY.>
	STR	<!
!	This file should be INCLUDEd any  FORTRAN  program
!	wanting  to  use  the  MAP subroutine.  Only flag,
!	constants, and  offset  definitions  are  in  this
!	file.   Read MAP.MAC for a complete discription of
!	the calling sequences for the  FORTRAN  and  MACRO
!	interfaces to MAP.
>
	OFFSET==0
	STR	<


!	Initialization block offsets
>
BLK%	.MPFNC, MPIFNC, 1		; Flag and function code word
BLK%	.MPNPC, MPINPC, 1		; Number of pages to cache
BLK%	.MPSPN, MPISPN, 1		; Starting page number
BLK%	.MPDSN, MPIDSN, 1		; Default section number
BLK%	.MPARG, MPIARG, 1		; Function dependant argument
					; zero for .MPMON
					; job number for .MPJOB
					; address of filespec for .MPFIL
BLK%	.MPMAX,	MPDMAX, 0		; Length of argument block

	STR	<

!	Initialization flags
>
SYM%	MP.PPM,	MPFPPM,	200000000000	; Physical page mapping
SYM%	MP.PAT,	MPFPAT,	100000000000	; Enable patching
SYM%	MP.EXE,	MPFEXE,	040000000000	; EXE file mapping
SYM%	MP.PIO,	MPFPIO,	020000000000	; Physical-only OPEN/LOOKUP on file
SYM%	MP.RTM,	MPFRTM,	010000000000	; Return run time statistics
SYM%	MP.SIO,	MPFSIO,	004000000000	; Super I/O
SYM%	MP.JRM,	MPFJRM,	002000000000	; Use JOBPEK UUOs instead of simulation
SYM%	MP.SPY,	MPFSPY,	001000000000	; Job needs to SPY

	STR	<

!	Mapping functions
>
SYM%	.MPMON,	MPFMON,	  0	; Map the running monitor (PEEK)
SYM%	.MPJOB,	MPFJOB,	  1	; Map a job in the running monitor (JOBPEK)
SYM%	.MPFIL,	MPFFIL,	  2	; Map a data or EXE file (FILDDT)
SYM%	.MPFMX,	MPFFMX,	  2	; Highest known mapping code

	STR	<

!	CPU type codes
>
SYM%	.PDP6,	PDP6,	  1	; CP166 processor
SYM%	.KA10,	KA10,	  2	; KA10 processor
SYM%	.KI10,	KI10,	  3	; KI10 processor
SYM%	.KL10,	KL10,	  4	; KL10 processor
SYM%	.KS10,	KS10,	  5	; KS10 processor
SYM%	.KC10,	KC10,	  6	; KC10 processor
	STR	<

!	Paging codes
>
SYM%	.KARPR,	KARPR,	  1	; KA Relocation & Protection Registers
SYM%	.KIPAG,	KIPAG,	  2	; KI paging on a KI10, KL10, or KS10
SYM%	.KLPAG,	KLPAG,	  3	; KL paging on a KL10 or KS10
SYM%	.KCPAG,	KCPAG,	  4	; KL paging on a KC10
	STR	<

!	Random constants
>
SYM%	.AP,	None,	  1	; MACRO AC for argument passing
SYM%	.MPEWD,	MPFEWD,	 30	; Length of ASCIZ error buffers
SYM%	.MPFWD,	MPFFWD,	 21	; Length of ASCIZ filespec in words

	OFFSET==0

	STR	<

!	Data block offsets
>
BLK%	.MPDAT,	MPDDAT,	  1	; Count of words in data block
BLK%	.MPVER,	MPDVER,	  1	; MAP version number
BLK%	.MPSPY,	MPDSPY,	  1	; Non-zero if SPYing
BLK%	.MPCPU,	MPDCPU,	  1	; CPU type
BLK%	.MPPAG,	MPDPAG,	  1	; Paging type
BLK%	.MPPGS,	MPDPGS,	  1	; Number of pages availble for mapping
BLK%	.MPCPC,	MPDCPC,	  1	; Cached page count
BLK%	.MPCPN,	MPDCPN,	  1	; Starting cached page number
BLK%	.MPSEC,	MPDSEC,	  1	; Default section number
Z.BSTS==OFFSET
BLK%	.MPPGC,	MPDPGC,	  1	; Count of mapped page creates
BLK%	.MPPGD,	MPDPGD,	  1	; Count of mapped page destroys
BLK%	.MPADR,	MPDADR,	  1	; Count of mapped address computations
BLK%	.MPEXM,	MPDEXM,	  1	; Count of mapped examines
BLK%	.MPDEP,	MPDDEP,	  1	; Count of mapped deposits
BLK%	.MPGTB,	MPDGTB,	  1	; Count of mapped GETTABs
BLK%	.MPGTU,	MPDGTU,	  1	; Count of GETTAB UUOs executed
BLK%	.MPJPK,	MPDJPK,	  1	; Count of mapped JOBPEK UUOs
BLK%	.MPJPU,	MPDJPU,	  1	; Count of JOBPEK UUOs executed
BLK%	.MPRTM,	MPDRTM,	  1	; Run time
BLK%	.MPHSF,	MPDHSF,	  1	; Count of hash table searches
Z.ESTS==OFFSET
BLK%	.MPHSC,	MPDHSC,	  1	; Count of hash table collisions
BLK%	.MPAFS,	MPDAFS,  .MPFWD	; Actual filespec
BLK%	.MPECD,	MPDECD,	  1	; Mapping error code
BLK%	.MPPFX,	MPDPFX,	  1	; Right justified sixbit prefix
BLK%	.MPMET,	MPDMET,	 .MPEWD	; Mapping error text
BLK%	.MPXET,	MPDXET,	 .MPEWD	; Extended error text
BLK%	.MPLEN,	MPDLEN,	  0	; Length of data block


IFN COMPILER,<END>
SUBTTL	Internal definitions





; Accumulators
;
	T1==1				;FOUR
	T2==2				; TEMPORARY
	T3==3				;  ACS
	T4==4				;   ...


	A1==5				;4 ACS USED FOR
	A2==6				; MAPPED ADDRESS
	A3==7				;  CALCULATIONS &
	A4==10				;   CACHE HANDLING

	VMA==11				;VIRTUAL MEMORY ADDRESS
	PMA==12				;PHYSICAL MEMORY ADDRESS
	SPT==13				;SPT BASE ADDRESS

	F==14				;FLAGS
	P==17				;PDL

	.AP==T1				;USER COMMUMICATES THROUGH THIS AC


; Random values
;
	PDLSIZ==50			;INTERNAL PDL SIZE
	PAGSIZ==1000			;SIZE OF A PAGE IN WORDS
	PAGNUM==^D20			;DEFAULT NUMBER OF PAGES TO MAP
	HGHPAG==700			;HIGHEST PAGE NUMBER +1 TO USE
	DEFPAG==HGHPAG-PAGNUM		;DEFAULT STARTING PAGE NUMBER
	ABSTAB==410			;ADDRESS OF POINTER TO NUMTAB
	DEFEPT==1000			;DEFAULT EPT ADDRESS
	DEFUEA==<<^D112*^D1024>-1>	;DEFAULT HIGHEST UNMAPPED EXEC ADDRESS
	DEFPBA==<^D112*^D1024>		;DEFAULT PER-PROCESS BEGINNING ADDRESS
	DEFPEA==<<^D112+^D16>*^D1024>	;DEFAULT PER-PROCESS ENDING ADDRESS
	DEFORG==400000			;DEFAULT MONITOR'S HIGH SEGMENT ORIGIN
	FOPSIZ==.FOMAX			;SIZE OF A FILOP. UUO BLOCK
	LERSIZ==.RBMAX			;SIZE OF A LOOKUP/ENTER UUO BLOCK
	PTHSIZ==.PTLEL			;SIZE OF A PATH. UUO BLOCK
	FILSIZ==.FOFMX			;SIZE OF A RETURNED FILESPEC BLOCK
; Cache blocks
;
	 ...X==.
	PHASE	0

.CBNHB:! BLOCK	1	;NEXT HASH BLOCK
.CBPHB:! BLOCK	1	;PREVIOUS HASH BLOCK
.CBNAB:! BLOCK	1	;NEXT ACCESSED BLOCK
.CBPAB:! BLOCK	1	;PREVIOUS ACCESS BLOCK
.CBPRC:! BLOCK	1	;PROCESS PAGE NUMBER
.CBUSR:! BLOCK	1	;USER PAGE NUMBER
.CBFLG:! BLOCK	1	;FLAGS
   CB.AVA==1B0		   ;CHUNK IS FREE
   CB.CRE==1B1		   ;USER PAGE HAS BEEN CREATED
   CB.PHY==1B2		   ;PHYSICAL PAGE (NOT VIRTUAL)
   CB.UPD==1B3		   ;UPDATE PAGE ON NEXT REPLACE
.CBLEN:!		;LENGTH

	 DEPHASE
;	 RELOC	...X
	 PURGE	...X


; Copy block offsets
;
	 ...X==.
	 PHASE	0

.CBWCT:! BLOCK	1	;WORD COUNT
.CBRAD:! BLOCK	1	;READ ADDRESS (SOURCE)
.CBWAD:! BLOCK	1	;WRITE ADDRESS (DESTINATION)
.CBXLN:!		;LENGTH

	 DEPHASE
;	 RELOC	...X
	 PURGE	...X
	SECTAB==540	;OFFSET IN EPT OR UPT OF FIRST SECTION MAP POINTER
	MXSECN==37	;MAXIMUM NUMBER OF SECTIONS ON A KL10


; Flags in AC 'F'
;
	FL.XXX==400000			;RESERVED
	FL.PPM==200000			;.MAPI FLAG - PHYSICAL PAGE MAPPING
	FL.PAT==100000			;.MAPI FLAG - PATCH
	FL.EXE== 40000			;.MAPI FLAG - .EXE FILE MAPPING
	FL.PIO== 20000			;.MAPI FLAG - PHYSICAL FILE I/O
	FL.RTM== 10000			;.MAPI FLAG - RETURN RUNTIM STATISTICS
	FL.SIO==  4000			;.MAPI FLAG - SUPER I/O
	FL.JRM==  2000			;.MAPI FLAG - JOBPEK UUOS ON MONITOR
	FL.SPY==  1000			;.MAPI FLAG - JOB NEEDS SPY/WE CAN SPY
	FL.INI==377000			;.MAPI FLAGS

	FL.EPM==   100			;EXEC PHYSICAL PAGE MAPPING
	FL.TPP==    40			;TEMPORARY PHYSICAL PAGE MAPPING
	FL.GTS==    20			;GETTAB SIMULATION SETUP
	FL.DEV==    10			;FILESPEC SCANNER - DEVICE
	FL.NAM==     4			;FILESPEC SCANNER - FILE NAME
	FL.EXT==     2			;FILESPEC SCANNER - EXTENSION
	FL.DIR==     1			;FILESPEC SCANNER - DIRECTORY

	FR.TYP==777777			;MAPPING TYPE
SUBTTL	.MAPC - Clear out mapper statistics


; Routine to clear out the mapper statistics block
; Call:	PUSHJ	P,.MAPC
;	  <NON-SKIP>
;	<SKIP>
;
.MAPC::	PUSHJ	P,CONTXT		;CONTEXT SWITCH
	MOVEI	T1,MAPDAT		;POINT TO START OF MAPPER DATA
	SETZM	Z.BSTS(T1)		;CLEAR FIRST WORD
	MOVSI	T2,Z.BSTS(T1)		;GET START ADDRESS
	HRRI	T2,Z.BSTS+1(T1)		;MAKE A BLT POINTER
	BLT	T2,Z.ESTS-1(T1)		;CLEAR THE BLOCK
	JRST	CPOPJ1			;AND RETURN
SUBTTL	.MAPD - Deposit


; Deposit into a mapped location
; Call:	MOVE	.AP, ADDR
;	PUSHJ	P,.MAPD
;	<NON-SKIP>		;FAILED
;	<SKIP>			;SUCEEDED, ACS UNCHANGED
;
; ADDR:	address to deposit into
;	old contents
;	new contents
;
.MAPD::	PUSHJ	P,CONTXT		;CONTEXT SWITCH
	MOVEI	T1,3			;3 WORDS IN BLOCK
	MOVE	T2,USRACS+.AP		;GET ARG POINTER
	MOVE	T1,0(T2)		;GET WORD 0
	MOVEM	T1,POKBLK+0		;SAVE
	MOVE	T1,1(T2)		;GET WORD 1
	MOVEM	T1,POKBLK+1		;SAVE
	MOVE	T1,2(T2)		;GET WORD 2
	MOVEM	T1,POKBLK+2		;SAVE
	MOVE	T1,POKBLK+0		;GET ADDRESS TO DESPOSIT INTO
	PUSHJ	P,ADDRESS		;COMPUTE A MAPPED ADDRESS
	  ERR.	(DAF,CPOPJ)		;DEPOSIT ADDRESS FAILURE
	MOVE	T2,(T1)			;GET CONTENTS
	CAME	T2,POKBLK+1		;WHAT THE USER THINKS IT SHOULD BE?
	  ERR.	(DVM,CPOPJ)		;DEPOSIT VALUE DOESN'T MATCH
	CAMN	T2,POKBLK+2		;OLD CONTENTS SAME AS NEW CONTENTS?
	JRST	CPOPJ1			;YES - THEN NOTHING TO DO
	MOVE	T3,POKBLK+2		;GET WORD TO DEPOSIT
	PUSHJ	P,@DEPTAB(F)		;DO IT
	  POPJ	P,			;FAILED
	AOS	MAPDAT+.MPDEP		;COUNT THE DEPOSIT
	JRST	CPOPJ1			;RETURN
SUBTTL	.MAPE - Examine


; Examine a mapped location
; Call:	MOVE	T1, address
;	PUSHJ	P,.MAPE
;	<NON-SKIP>		;FAILED
;	<SKIP>			;SUCEEDED, T1:= C(ADDR)
;
.MAPE::	PUSHJ	P,CONTXT		;CONTEXT SWITCH
	MOVE	T1,USRACS+.AP		;GET REAL T1
	PUSHJ	P,EXAMINE		;DO THE EXAMINE
	  POPJ	P,			;CAN'T
	MOVEM	T1,USRACS+.AP		;STORE IN REAL T1
	JRST	CPOPJ1			;RETURN


PEXAMINE:TLOA	F,FL.TPP		;ALLOW PHYSICAL PAGE MAPPING
VEXAMINE:TLZ	F,FL.TPP		;ALLOW VIRTUAL PAGE MAPPING

EXAMINE:PUSHJ	P,ADDRESS		;COMPUTE MAPPED ADDRESS
	  ERR.	(EAF,CPOPJ)		;EXAMINE ADDRESS FAILURE
	MOVE	T1,(T1)			;GET CONTENTS
	AOS	MAPDAT+.MPEXM		;COUNT THE EXAMINE
	JRST	CPOPJ1			;AND RETURN
SUBTTL	.MAPG - GETTAB UUO simulation


; This routine will simulate a GETTAB UUO.  The calling sequence is exactly
; like a GETTAB UUO.  If the simulation fails, and monitor mapping is being
; done, a GETTAB UUO will be tried.  A skip return implies the requested
; monitor information has been retrieved.  A non-skip return means the GETTAB
; arguments are illegal.
;
; Historical note:
; The GETTAB UUO (CALLI 41) is new with the 3.19 monitor release.  The UUO was
; implemented to allow unprivileged programs to examine various monitor tables.
; CALL:	HRROI AC, MONITOR JOB TABLE NUMBER	;NEG. TABLES FOR CUSTOMER
;	HRLI AC, JOB NUMBER			;LH .EQ. -1 CURRENT JOB
;						;LH .EQ. -2 CURRENT HIGH-SEG
;	CALL AC, [SIXBIT /GETTAB/]		;OR CALLI AC,41
;
.MAPG::	PUSHJ	P,CONTXT		;CONTEXT SWITCH
	MOVE	T1,USRACS+.AP		;GET REAL T1
	PUSHJ	P,GTBSIM		;DO THE GETTAB SIMULATION
	  SKIPA				;FAILED
	AOS	(P)			;SKIP
	MOVEM	T1,USRACS+.AP		;STORE IN REAL T1
	POPJ	P,			;AND RETURN

GTBSIM:	MOVEM	T1,GTBARG		;SAVE THE ARGUMENT
	HRRES	T1			;GET THE TABLE NUMBER
	CAIN	T1,.GTIDX		;RANGE TABLE?
	HLRE	T1,GTBARG		;YES--GET INDEX (TABLE NUMBER)
	ADD	T1,NUMTAB		;OFFSET INTO NUMTAB
	PUSHJ	P,EXAMINE		;READ NUMTAB ENTRY
	  JRST	GTBS.1			;MAYBE NO PRIVS
	MOVEM	T1,GTBNUM		;STORE FOR LATER
	LDB	T1,GTBTYP		;GET TABLE TYPE CODE
	TLNE	F,FL.GTS		;GETTAB SIMULATION SETUP?
	CAIL	T1,GTBLEN		;DO WE KNOW ABOUT THIS TABLE?

GTBS.1:	MOVEI	T1,0			;NO--INDEX ZERO TO ATTEMPT GETTAB UUO
	MOVEM	T1,GTBIDX		;SAVE INDEX FOR LATER
	HRRZ	T2,GTBARG		;GET THE TABLE NUMBER
	CAIN	T2,.GTIDX		;THE RANGE TABLE?
	MOVEI	T1,.SLIXR		;YES
	PUSHJ	P,@GTBTAB(T1)		;DO SOMETHING
	  SKIPA	T1,GTBIDX		;GET INDEX IF SIMULATION FAILED
	JRST	GTBS.2			;GOT IT
	JUMPN	T1,GTBS.1		;TRY THE UUO IF WE CAN
	MOVE	T1,GTBARG		;LOST AGAIN--RELOAD THE ARGUMENT
	ERR.	(GUF,CPOPJ)		;GETTAB UUO/SIMULATION FAILED

GTBS.2:	AOS	MAPDAT+.MPGTB		;COUNT THE GETTAB
	JRST	CPOPJ1			;RETURN

; GETTAB simulator dispatch table
;
GTBTAB:	EXP	UNKNTB			;UNKNOWN TABLE
	EXP	ITEMTB			;ITEM NUMBER
	EXP	JOBNTB			;JOB NUMBER
	EXP	SEGNTB			;SEGMENT NUMBER
	EXP	JPDBTB			;JOB NUMBER (DATA IN PDB)
	EXP	RNGETB			;NEGATIVE AND POSITIVE NUMBERS
GTBLEN==.-GTBTAB			;LENGTH OF TABLE
; Byte pointers to parts of GETTAB arguments.
;
GTBMAX:	POINTR	(GTBNUM,SL.MAX)		;MAXIMUM ITEM NUMBER IN TABLE
GTBTYP:	POINTR	(GTBNUM,SL.TYP)		;TYPE OF TABLE IDENTIFIER
GTBMAC:	POINTR	(GTBNUM,SL.MAC)		;A MONITOR AC NUMBER
GTBADR:	POINTR	(GTBNUM,SL.ADR)		;EXECUTIVE MODE ADDRESS OF TABLE IF
					; SL.TYP=1,2,3 OR OFFSET TO PDB IF
					; SL.TYP=4


; GETTAB table types. The values here MUST correspond to the order of
; GTBTAB. They are included for documentation purposes and to force
; them into the symbol table, but are never referenced directly.
;
	.SLNIC==.SLNIC		;(0) NOT INCLUDED IN THIS CONFIGURATION
	.SLIXI==.SLIXI		;(1) INDEX BY ITEM NUMBER
	.SLIXJ==.SLIXJ		;(2) INDEX BY JOB NUMBER
	.SLIXS==.SLIXS		;(3) INDEX BY JOB NUMBER OR SEGMENT NUMBER
	.SLIXP==.SLIXP		;(4) INDEX BY JOB NUMBER (DATA IN PDB)
	.SLIXR==.SLIXR		;(5) INDEX BY NEGATIVE AND POSITIVE OFFSETS
				;    BITS 12,13 RESERVED FOR DEC


; Masks of low and high ranges of GETTAB tables indexed by negative and
; positive numbers (table type SL.IXR).  These are never referenced but
; are included for documantaion and to force the symbols into the symbol
; table.
;
	ID.MIN==ID.MIN		;LOW RANGE OF TABLE
	ID.MAX==ID.MAX		;HIGH RANGE OF TABLE
; Unknown table type
;
UNKNTB:	MOVE	T1,GTBARG		;PICK UP USER ARGUMENTS
	HRRZ	T2,F			;GET JUST THE MAPPING TYPE
	CAIN	T2,.MPMON		;MAPPING A RUNNING MONITOR?
	GETTAB	T1,			;YES - TRY THE GETTAB UUO
	  SOS	(P)			;LOSE
	AOS	MAPDAT+.MPGTU		;COUNT NUMBER OF GETTAB UUOS EXECUTED
	JRST	CPOPJ1			;RETURN


; Item table type
;
ITEMTB:	HLRE	T1,GTBARG		;GET REQUESTED ITEM NUMBER
	LDB	T2,GTBMAX		;GET MAXIMUM LENGTH OF THE TABLE
	SKIPL	T1			;NEGATIVE INDEX IS ILLEGAL
	CAMLE	T1,T2			;WITHIN LEGAL RANGE?
	  POPJ	P,			;NOPE
	LDB	T2,GTBADR		;GET TABLE BASE ADDRESS
	ADD	T1,T2			;OFFSET INTO TABLE
	PUSHJ	P,EXAMINE		;GET C(T1)
	  POPJ	P,			;CAN'T
	JRST	CPOPJ1			;RETURN SUCESSFUL


; Job table type
;
JOBNTB:	HLRE	T1,GTBARG		;GET JOB NUMBER
	CAMN	T1,[-1]			;OUR JOB?
	MOVE	T1,USRJOB		;YES - GET IT
	SKIPL	T1			;CAN'T HAVE A NEGATIVE JOB NUMBER
	CAMLE	T1,JOBN			;WITHIN LEGAL RANGE?
	  POPJ	P,			;NOPE
	LDB	T2,GTBADR		;GET TABLE BASE ADDRESS
	ADD	T1,T2			;INDEX INTO TABLE
	PUSHJ	P,EXAMINE		;GET C(T1)
	  POPJ	P,			;CAN'T
	JRST	CPOPJ1			;RETURN SUCESSFUL
; Segment table type
;
SEGNTB:	HLRE	T1,GTBARG		;GET SEGMENT NUMBER
	CAMN	T1,[-1]			;OUR JOB NUMBER?
	MOVE	T1,USRJOB		;YES - LOAD OUR JOB NUMBER
	CAME	T1,[-2]			;OUR SEGMENT NUMBER?
	JRST	SEGN.1			;NO
	MOVE	T1,JBTSGN		;GET JOB TO SEG TRANSLATION
	ADD	T1,USRJOB		;ADD IN OUR JOB NUMBER
	PUSHJ	P,EXAMINE		;GET C(T1)
	  POPJ	P,			;CAN'T
	HRRZS	T1			;KEEP JUST THE SEGMENT NUMBER
	JUMPE	T1,CPOPJ		;RETURN IF NO HIGH SEGMENT

SEGN.1:	SKIPL	T1			;CAN'T HAVE NEGATIVE JOB OR SEG NUMBERS
	CAMLE	T1,SEGN			;WITHIN LEGAL RANGE?
	  POPJ	P,			;NOPE
	LDB	T2,GTBADR		;GET TABLE BASE ADDRESS
	ADD	T1,T2			;OFFSET INTO TABLE
	PUSHJ	P,EXAMINE		;GET C(T1)
	  POPJ	P,			;CAN'T
	JRST	CPOPJ1			;RETURN SUCESSFUL


; PDB table type
;
JPDBTB:	HLRE	T1,GTBARG		;GET INDEX
	CAMN	T1,[-1]			;IS IT OUR JOB?
	MOVE	T1,USRJOB		;YES - LOAD JOB NUMBER
	SKIPL	T1			;CAN'T HAVE NEGATIVE JOB NUMBERS
	CAMLE	T1,JOBN			;WITHIN LEGAL RANGE?
	  POPJ	P,			;NOPE
	ADD	T1,JBTPDB		;OFFSET INTO JBTPDB
	PUSHJ	P,EXAMINE		;GET C(T1)
	  POPJ	P,			;CAN'T
	JUMPE	T1,CPOPJ		;A PDB FOR REQUESTED JOB?
	HRRZS	T1			;KEEP JUST THE ADDRESS
	LDB	T2,GTBADR		;GET INDEX INTO THE PDB
	ADD	T1,T2			;OFFSET INTO THE PDB
	PUSHJ	P,EXAMINE		;GET C(T1)
	  POPJ	P,			;CAN'T
	JRST	CPOPJ1			;RETURN SUCESSFUL
RNGETB:	LDB	T1,GTBMAX		;GET MAXIMUM LENGTH OF THE TABLE
	LDB	T2,GTBTYP		;GET TABLE TYPE?
	CAIE	T2,.SLIXR		;INDEXED BY RANGE?
	JRST	CPOPJ1			;NO--FAKED OUT BY GTBSIM
	ADD	T1,RNGTAB		;INDEX INTO RNGTAB
	PUSHJ	P,EXAMINE		;GET RANGE OF GETTAB TABLE
	  POPJ	P,			;CAN'T
	MOVEM	T1,GTBRNG		;SAVE RANGE
	HLRE	T2,T1			;GET LOWER LIMIT
	HRRE	T3,T1			;GET UPPER LIMIT
	HLRE	T1,GTBARG		;GET USER SUPPLIED INDEX
	CAMG	T1,T3			;GREATER THAN UPPER LIMIT?
	CAMGE	T1,T2			;GREATER THAN OR EQUAL TO LOWER LIMIT?
	  POPJ	P,			;NOPE
	HRRE	T2,GTBARG		;GET SUPPLIED TABLE NUMBER
	CAIN	T2,.GTIDX		;RANGE TABLE?
	JRST	RNGE.1			;YES
	LDB	T2,GTBADR		;GET THE BASE ADDRESS OF THE TABLE
	ADD	T1,T2			;ADD OFFSET
	PUSHJ	P,EXAMINE		;GET C(T1)
	  POPJ	P,			;CAN'T
	JRST	CPOPJ1			;RETURN SUCESSFUL

RNGE.1:	MOVE	T1,GTBRNG		;GET LOWER,,UPPER LIMITS
	JRST	CPOPJ1			;AND RETURN
SUBTTL	.MAPI - Initialization


; This routine MUST be called before all others
; Call:	MOVE	.AP, flags + argument
;	PUSHJ	P,.MAPI
;	<NON-SKIP>		;FAILED
;	<SKIP>			;SUCEEDED
;
.MAPI::	PUSH	P,T1			;SAVE T1
	PUSH	P,FILCHN		;SAVE OLD CHANNEL NUMBER
	MOVE	T1,[ZBEG,,ZBEG+1]	;SET UP BLT
	SETZM	ZBEG			;CLEAR FIRST WORD
	BLT	T1,ZEND-1		;CLEAR OUR DATA STORAGE
	POP	P,FILCHN		;RESTORE OLD CHANNEL NUMBER
	POP	P,T1			;RESTORE T1
	SETOM	CTXFLG			;INIT CONTEXT FLAG
	PUSHJ	P,CONTXT		;SAVE THE WORLD
	PUSHJ	P,DATINI		;GET INITIALIZE DATA
	  JRST	MAPI.E			;CAN'T
	PUSHJ	P,CSHCLR		;CLEAR OUT THE CACHE
	PUSHJ	P,CSHMAP		;MAP THE HASH TABLE AND CHUNK PAGES
	  JRST	MAPI.E			;FAILED
	PUSHJ	P,FILCLS		;CLOSE OFF CHANNEL FROM PREVIOUS CALL
	PUSHJ	P,@INITAB(F)		;SETUP MAPPING
	  JRST	MAPI.E			;FAILED
	PUSHJ	P,CSHINI		;SET UP HASH TABLE CHUNKS AND LINKS
	MOVE	A1,PAGCNT		;GET COUNT OF AVAILABLE PAGES
	SETZM	PAGCNT			;SO WE DON'T CONFUSE THINGS
	PUSHJ	P,CSHSIZ		;SET UP CACHE SIZE
	  JRST	MAPI.E			;CAN'T
	PUSHJ	P,SPYCHK		;SEE IF WE NEED TO SPY
	  JRST	MAPI.E			;NEED TO BUT CAN'T DO IT
	PUSHJ	P,GTBINI		;INITIALIZE GETTAB STUFF
	AOS	(P)			;SKIP

MAPI.E:	MOVEI	T1,MAPDAT		;GET ADDRESS OF DATA BLOCK
	MOVEM	T1,USRACS+.AP		;GIVE IT TO THE CALLER
	POPJ	P,			;RETURN
; Data block setup
;
DATINI:	MOVEI	T1,.MPLEN		;GET LENGTH OF DATA BLOCK
	MOVEM	T1,MAPDAT+.MPDAT	;SAVE IT
	MOVE	T1,[%%MAP]		;GET OUR VERSION
	MOVEM	T1,MAPDAT+.MPVER	;SAVE IT
	MOVE	T2,USRACS+.AP		;GET ARG POINTER
	MOVE	F,.MPFNC(T2)		;GET FLAGS AND MAPPING TYPE
	AND	F,[FL.INI,,FR.TYP]	;MAKE SURE THERE'S NO JUNK
	HRRZ	T1,F			;JUST THE MAPPING TYPE
	CAILE	T1,.MPFMX		;A GOOD NUMBER?
	ERR.	(IMC,CPOPJ)		;ILLEGAL MAPPING TYPE

DATI.1:	SKIPN	T1,.MPNPC(T2)		;GET NUMBER OF PAGES TO USE
	MOVEI	T1,PAGNUM		;NONE--LOAD DEFAULT
	SKIPE	T3,.MPSPN(T2)		;GET STARTING PAGE NUMBER
	JRST	DATI.2			;GOT SOMETHING
	MOVEI	T3,HGHPAG		;GET HIGHEST PAGE TO USE
	SUBI	T3,(T1)			;T2:= STARTING PAGE NUMBER

DATI.2:	MOVEM	T1,MAPDAT+.MPPGS	;SAVE FOR CURIOUS PROGRAMS
	MOVEM	T1,PAGCNT		;SAVE PAGE COUNT
	MOVEM	T3,MAPDAT+.MPCPN	;SAVE FOR CURIOUS PROGRAMS
	SKIPGE	T1,.MPDSN(T2)		;GET DEFAULT SECTION NUMBER
	MOVEI	T1,0			;ASSUME ZERO IF CALLER IS STUPID
	MOVEM	T1,MAPDAT+.MPSEC	;SAVE IT
	JRST	CPOPJ1			;RETURN
; See if we can SPY and if it's required
;
SPYCHK:	MOVEM	F,MAPFLG		;SAVE THE FLAGS
	AOS	MAPDAT+.MPSPY		;ASSUME IT'S ALL GONNA WORK
	TLO	F,FL.SPY		;CHEAT AND PRETEND WE CAN SPY
	MOVEI	T1,0			;AN ADDRESS TO LOOK AT
	PUSHJ	P,PADDRESS		;LOAD IT INTO THE CACHE
	  SKIPA	F,MAPFLG		;CAN'T
	JRST	CPOPJ1			;GUESS WE CAN SPY
	SETZM	MAPDAT+.MPSPY		;SO THE CALLER KNOW WHATS GOING ON
	TLZE	F,FL.SPY		;DO WE NEED TO SPY?
	ERR.	(ECS,CPOPJ)		;YES--AND WE CAN'T DO IT!
	JRST	CPOPJ1			;RETURN
; Determine the environment for GETTABing.  This routine will try
; to figure out the CPU and paging type by looking at the Exec Data
; Vector and other data.  If sucessful, some basic GETTABs will be
; performed for use later during GETTAB simulation.
;
GTBINI:	TLNE	F,FL.PPM		;PHYSICAL PAGE MAPPING?
	POPJ	P,			;THEN GETTABS ARE MEANINGLESS
	SETZM	HGHUEA			;DON'T KNOW THIS ONE YET
	PJOB	T1,			;GET OUR JOB NUMBER
	MOVEM	T1,USRJOB		;SAVE IT
	SETZ	T2,			;INIT INDEX

GTBI.1:	MOVE	T1,GTBEXT+0(T2)		;GET LOCATION
	SKIPE	GTBEXT+1(T2)		;HAVE AN OFFSET?
	ADD	T1,@GTBEXT+1(T2)	;YES--ADD IT IN
	PUSHJ	P,PEXAMINE		;GET C(T1)
	  JRST	GTBI.2			;CAN'T
	MOVEM	T1,@GTBEXT+2(T2)	;STORE RESULT
	ADDI	T2,3			;ACCOUNT FOR THREE WORD ENTRIES
	CAIGE	T2,GTBEXL		;OFF THE END OF THE TABLE?
	JRST	GTBI.1			;NO--LOOP
	HLRZ	T1,EDVCNT		;GET EDV CODE
	HRRZ	T2,EDVCNT		;GET WORD COUNT
	CAIN	T1,'EDV'		;LOOKING AT AN EDV?
	CAIGE	T2,.EDEPT		;AND DOES THIS EDV CONTAIN NEEDED DATA?
	JRST	GTBI.2			;NO
	MOVE	T1,EDVDAT		;GET FLAGS AND CPU DATA
	TLNE	T1,(ED.KLP)		;THIS A KL PAGING MACHING?
	SETOM	KLPFLG			;YES
	HRRZM	T1,MAPDAT+.MPCPU	;SAVE CPU TYPE
	JRST	GTBI.3			;GO CHECKOUT THE PAGING
; Determine the CPU type.  Here if the EDV contains junk or unreasonable
; data.  We know at this point that the monitor is pre-702 because the EDV
; is invalid.  This implies that the first 112K of the monitor is unmapped
; (KA10 or KI10), or mapped one-for-one virtual-to-physical (KL10).
;
GTBI.2:	MOVE	T1,[%CCTYP]		;ARGUMENT TO RETURN CPU TYPE
	PUSHJ	P,GTBFRC		;TRY THE BRUTE FORCE METHOD
	  POPJ	P,			;CAN'T
	MOVEM	T1,MAPDAT+.MPCPU	;SAVE IT
	SETZM	EPTADR			;DON'T BELEIVE THE EPT ADDRESS
	SETZM	KLPFLG			;CLEAR THE KL PAGING FLAG


; Get the paging type
;
GTBI.3:	SKIPN	T1,MAPDAT+.MPCPU	;GET CPU TYPE CODE
	POPJ	P,			;UNKNOWN CPU TYPE
	MOVEI	T2,.KARPR		;KA RELOCATION AND PROTECTION REGISTERS
	CAIE	T1,.PDP6		;CP166 CPU?
	CAIN	T1,.KA10		;KA10 CPU?
	JRST	GTBI.4			;YES TO EITHER
	CAIE	T1,.KI10		;A KI10 CPU?
	SKIPN	KLPFLG			;WHAT KIND OF PAGING?
	SKIPA	T2,[.KIPAG]		;KI10
	MOVEI	T2,.KLPAG		;KL10
	CAIN	T1,.KC10		;KC10 CPU?
	MOVEI	T2,.KCPAG		;A DIFFERENT FLAVOR OF KL PAGING

GTBI.4:	MOVEM	T2,MAPDAT+.MPPAG	;SAVE PAGING TYPE
	SKIPLE	EPTADR			;HAVE AN EDV?
	JRST	GTBI.5			;YES--MUST ASSUME THE EPT IS OK
	MOVE	T1,[%CCTOS]		;ARGUMENT TO RETURN THE EPT ADDRESS
	PUSHJ	P,GTBFRC		;TRY TO GET IT
	  POPJ	P,			;LOSE
	MOVEM	T1,EPTADR		;SET IT
	JRST	GTBI.5			;GO DO SOME BASIC GETTABS
; Do some basic GETTABs needed later for GETTAB simulation
;
GTBI.5:	TLO	F,FL.GTS		;LET GTBSIM DO IT'S STUFF
	SETZ	T4,			;CLEAR INDEX

GTBI.6:	MOVE	T1,GTBGTT+0(T4)		;GET A GETTAB ARGUMENT
	PUSHJ	P,GTBSIM		;SIMULATE A GETTAB
	  XCT	GTBGTT+1(T4)		;DEFAULT VALUE OR RETURN
	XCT	GTBGTT+2(T4)		;SAVE VALUE
	ADDI	T4,2			;ACCOUNT FOR THREE WORD ENTRIES
	CAIGE	T4,GTBGTL-1		;END OF THE TABLE?
	AOJA	T4,GTBI.6		;NO--LOOP
	MOVMS	SEGN			;MAKE SEGN POSITIVE
	MOVE	T1,JOBN			;GET THE NUMBER OF JOBS
	ADDM	T1,SEGN			;ADD TO TOTAL OF SEGMENTS


; Here to see if the monitor's high segment is mapped yet.  We GETTAB
; the system uptime.  If it's not equal to zero, then the monitor
; probably ran for some amount of time and the high segment must have
; been mapped.
;
GTBI.7:	MOVE	T1,[%CNSUP]		;SYSTEM UPTIME IN TICS
	PUSHJ	P,GTBFRC		;READ FROM MONITOR/.EXE FILE
	  SETZ	T1,			;CAN'T READ, ASSUME NOT "MAPPED"
	MOVEM	T1,HIFLAG		;IF .NE. 0 THEN "HISEG MAPPED"
	POPJ	P,			;RETURN
; Here to do a GETTAB by the brute force method
;
GTBFRC:	SKIPE	HGHUEA			;KNOW THIS ADDR YET?
	JRST	GTBF.1			;YES
	MOVEI	T2,DEFUEA		;GET DEFAULT HIGHEST UNMAPPED ADDR
	MOVEM	T2,HGHUEA		;SAVE TO WE DON'T DO PHYSICAL MAPPING
	PUSHJ	P,GTBF.1		;DO THE GETTAB
	  SKIPA				;FAILED
	AOS	(P)			;SKIP
	SETZM	HGHUEA			;PUT BACK THE WAY WE FOUND IT
	POPJ	P,			;AND RETURN

GTBF.1:	TLO	F,FL.GTS		;ALLOW GTBSIM TO DO ITS STUFF
	PUSHJ	P,GTBSIM		;TRY THE GETTAB
	  POPJ	P,			;FAILED
	JRST	CPOPJ1			;RETURN


; Here when we can't determine how to do GETTABs
;
GTBI.E:	TLZ	F,FL.GTS		;COULDN'T SETUP GETTAB SIMULATION
	POPJ	P,			;RETURN


; Table of locations, offsets, and storage words
;
GTBEXT:	EXP	ABSTAB,000000,NUMTAB	;TABLE OF GETTAB TABLE POINTERS
	EXP	.JBEDV,000000,EDVADR	;EDV ADDRESS
	EXP	.EDCNT,EDVADR,EDVCNT	;EDV CODE AND WORD COUNT
	EXP	.EDDAT,EDVADR,EDVDAT	;FLAGS AND CPU DATA
	EXP	.EDEPT,EDVADR,EPTADR	;EPT ADDRESS
	EXP	.EDSPT,EDVADR,SPTADR	;SPT ADDRESS
GTBEXL==<.-GTBEXT>			;LENGTH OF TABLE


; Table of GETTAB arguments, defaults, and storage words
;
GTBGTT:
EXP <%VMHUA>,<MOVEI T1,DEFUEA>,<MOVEM T1,HGHUEA>;HIGHEST UNMAPPED EXEC ADDRESS
EXP <%VMPPB>,<MOVEI T1,DEFPBA>,<MOVEM T1,PPABEG>;BEGINING PER-PROCESS ADDRESS
EXP <%VMPPE>,<MOVEI T1,DEFPEA>,<MOVEM T1,PPAEND>;END PER-PROCESS ADDRESS
EXP <%CNSJN>,<POPJ P,>,<HRRZM T1,JOBN>		;HIGHEST LEGAL JOB
EXP <%CNSJN>,<POPJ P,>,<HLREM T1,SEGN>		;HIGHEST LEGAL SEGMENT
EXP <%CNPDB>,<POPJ P,>,<HRRZM T1,JBTPDB>	;JBTPDB POINTER
EXP <%CNVSH>,<MOVEI T1,DEFORG>,<MOVEM T1,HIORG>	;HIGH SEGMENT ORIGIN
EXP <.GTSGN,,.GTSLF>,<POPJ P,>,<HRRZM T1,JBTSGN>;JBTSGN POINTER
EXP <.GTIDX,,.GTSLF>,<POPJ P,>,<HRRZM T1,RNGTAB>;RNGTAB POINTER
EXP <.GTADR,,.GTSLF>,<POPJ P,>,<HRRZM T1,JBTADR>;JBTADR POINTER
EXP <.GTUPM,,.GTSLF>,<POPJ P,>,<HRRZM T1,JBTUPM>;JBTUPM POINTER
GTBGTL==.-GTBGTT				;LENGTH OF TABLE
SUBTTL	.MAPJ - JOBPEK UUO simulation


; Simulate the JOBPEK UUO by by actually tracing down section and
; page maps for all types of paging.
; Call:	MOVE	.AP, argument address
;	PUSHJ	P,.MAPJ
;	<NON-SKIP>			;FAILED
;	<SKIP>				;SUCEEDED
;
; Arg + 0/ <flags>B9+<job>B17+<wordcount>B35
; Arg + 1/ read address,,write address
;
; All legal JOBPEK flags are valid
;
.MAPJ::	PUSHJ	P,CONTXT		;CONTEXT SWITCH
	MOVE	T2,USRACS+.AP		;GET ARG POINTER
	HRRZ	T3,F			;GET MAPPING CODE
	CAIN	T3,.MPMON		;MAPPING THE RUNNING MONITOR?
	TLNN	F,FL.JRM		;JOBPEK UUOS ON THE RUNNING MONITOR?
	SKIPA	T1,.MPFNC(T2)		;NO--GET FLAG WORD
	JRST	[JOBPEK	T2,		;DO THE UUO
		   ERR.	(JRW,CPOPJ)	;JOBPEK FAILED TO READ/WRITE JOB
		 AOS	MAPDAT+.MPJPU	;COUNT THE JOBPEK UUO EXECUTION
		 JRST	CPOPJ1]		;RETURN
	MOVEM	T1,JPKFLG		;SAVE
	HRRZM	T1,CPYBLK+.CBWCT	;SAVE WORD COUNT
	HLRZ	T1,1(T2)		;GET THE READ ADDRESS
	MOVEM	T1,CPYBLK+.CBRAD	;SAVE IT
	HRRZ	T1,1(T2)		;GET THE WRITE ADDRESS
	MOVEM	T1,CPYBLK+.CBWAD	;SAVE IT
	PUSHJ	P,JPKSIM		;SIMULATE A JOBPEK UUO
	  POPJ	P,			;CAN'T
	JRST	CPOPJ1			;AND RETURN


; Here on internal calls
;
JPKSIM:	MOVE	T1,JPKFLG		;GET FLAG WORD
	TLNE	T1,(JK.UPM)		;READ A UPMP?
	JRST	JPKUPM			;YES
	TLNE	T1,(JK.EVA)		;READ EVM?
	JRST	JPKEVA			;YES
	JRST	JPKRED			;GO READ


; All sucessful JOBPEK code should exit through here
;
JPKXIT:	AOS	MAPDAT+.MPJPK		;COUNT THE JOBPEK SIMULATION
	JRST	CPOPJ1			;RETURN
; JOBPEK read
;
JPKRED:	LDB	T1,[POINT 9,JPKFLG,17]	;GET JOB NUMBER
	PUSHJ	P,PHYUPT		;GET UPT ADDRESS
	  POPJ	P,			;CAN'T
	MOVE	VMA,CPYBLK+.CBRAD	;GET READ ADDRESS
	PUSHJ	P,PHYADR		;MAKE IT ADDRESSIBLE
	  ERR.	(JNA,CPOPJ)		;JOB NOT ADDRESSABLE
	MOVEM	PMA,CPYBLK+.CBRAD	;SAVE READ ADDRESS
	MOVEI	T1,CPYBLK		;POINT TO COPY BLOCK
	PUSHJ	P,ADRCPY		;MOVE SOME DATA
	SKIPE	.CBWCT(T1)		;MORE WORDS TO PROCESS?
	JRST	JPKRED			;YES--LOOP BACK FOR MORE
	JRST	JPKXIT			;FINISH UP


; JOBPEK UPMP read
;
JPKUPM:	TLNE	T1,(JK.WRT)		;WANT TO WRITE THE UPMP?
	  ERR.	(IWU,CPOPJ)		;ILLEGAL TO WRITE THE UPMP
	HLRZS	T1			;GET HALF WORD WITH JOB NUMBER
	ANDI	T1,777			;KEEP JUST THE JOB NUMBER
	PUSHJ	P,PHYUPT		;GET THE UPT ADDRESS
	  POPJ	P,			;CAN'T
	MOVE	T1,PMA			;GET UPMP ADDRESS
	PUSHJ	P,PADDRESS		;MAKE IT ADDRESSABLE
	  ERR.	(JNA,CPOPJ)		;JOB NOT ADDRESSABLE
	MOVEM	T1,CPYBLK+.CBRAD	;SAVE READ ADDRESS
	MOVEI	T1,CPYBLK		;POINT TO COPY BLOCK
	PUSHJ	P,ADRCPY		;MOVE SOME DATA
	SKIPE	.CBWCT(T1)		;MORE WORDS TO PROCESS?
	JRST	JPKUPM			;YES--LOOP BACK FOR MORE
	JRST	JPKXIT			;FINISH UP


; JOBPEK exec virtual address read
;
JPKEVA:	TLNE	T1,(JK.WRT)		;WANT TO WRITE EVM?
	  ERR.	(IWE,CPOPJ)		;ILLEGAL TO WRITE EVM

JPKE.1:	LDB	T1,[POINT 9,JPKFLG,17]	;GET JOB WE'RE GONNA LOOK AT
	PUSHJ	P,PHYUPT		;GET IT'S UPT ADDRESS
	  POPJ	P,			;CAN'T
	MOVE	VMA,CPYBLK+.CBRAD	;GET ADDRESS TO CONVERT
	PUSHJ	P,PHYFUN		;COMPUTE MAPPED PHYSICAL FUNNY ADDRESS
	  POPJ	P,			;CAN'T
	MOVEM	PMA,CPYBLK+.CBRAD	;SAVE READ ADDRESS
	MOVEI	T1,CPYBLK		;POINT TO COPY BLOCK
	PUSHJ	P,ADRCPY		;MOVE SOME DATA
	SKIPE	.CBWCT(T1)		;MORE WORDS TO PROCESS?
	JRST	JPKE.1			;YES--LOOP BACK FOR MORE
	JRST	JPKXIT			;FINISH UP
SUBTTL	Address mapping -- Compute a mapped address


; Call:	MOVE	T1, address
;	PUSHJ	P,ADDRESS
;	<return>
;
PADDRESS:TLOA	F,FL.TPP		;ALLOW PHYSICAL PAGE MAPPING
VADDRESS:TLZ	F,FL.TPP		;ALLOW VIRTUAL PAGE MAPPING

ADDRESS:TLZE	T1,400000		;CLEAR "SECTION RELATIVE" REFERENCES
	HRL	T1,MAPDAT+.MPSEC	;LOAD DEFAULT SECTION NUMBER
	TLNN	F,FL.SPY		;CAN WE SPY?
	ERR.	(ECS,CPOPJ)		;NO
	TLNN	F,FL.PPM!FL.TPP		;PHYSICAL PAGE MAPPING?
	PUSHJ	P,@CVTTAB(F)		;SEE IF NECESSARY TO CONVERT ADDRESS
	  JRST	ADDR.1			;NO ADDRESS FIXUP NECESSARY
	PUSHJ	P,SAVEF			;SAVE F
	PUSHJ	P,PHYEPT		;GET PHYSICAL EPT ADDRESS
	  POPJ	P,			;CAN'T
	MOVE	VMA,T1			;GET ADDRESS TO CONVERT
	PUSHJ	P,PHYADR		;COMPUTE MAPPED PHYSICAL ADDRESS
	  POPJ	P,			;CAN'T
	MOVE	T1,PMA			;GET ADDRESS OF MAPPED PHYSICAL ADDRESS
	AOS	MAPDAT+.MPADR		;COUNT ADDRESS COMPUTATIONS
	JRST	CPOPJ1			;AND RETURN

ADDR.1:	MOVE	A1,T1			;GET ADDRESS TO MAP
	LSH	A1,-11			;CONVERT TO A PAGE NUMBER
	PUSHJ	P,CSHFND		;SEE IF PAGE IN CACHE
	  JRST	ADDR.2			;NOT FOUND
	PUSHJ	P,CSHMRU		;MOVE TO TOP OF LIST
	JRST	ADDR.4			;ONWARD

ADDR.2:	PUSHJ	P,CSHINS		;INSERT PAGE IN CACHE
	MOVSI	A3,(CB.CRE)		;GET A BIT
	TDNN	A3,.CBFLG(A2)		;PAGE ALREADY EXIST?
	JRST	ADDR.3			;NO
	PUSHJ	P,@DESTAB(F)		;DESTROY THE PAGE
	  POPJ	P,			;CAN'T
	AOS	MAPDAT+.MPPGD		;COUNT PAGE DESTROY

ADDR.3:	MOVE	A1,T1			;GET ADDRESS WE'RE GOING TO MAP
	LSH	A1,-11			;KEEP JUST THE PAGE NUMBER
	MOVEM	A1,.CBPRC(A2)		;STORE NEW PROCESS PAGE NUMBER
	PUSHJ	P,@CRETAB(F)		;CREATE THE PAGE
	  POPJ	P,			;CAN'T
	AOS	MAPDAT+.MPPGC		;COUNT PAGE CREATE

ADDR.4:	MOVE	A1,.CBUSR(A2)		;GET USER PAGE NUMBER
	LSH	A1,11			;CONVERT TO AN ADDRESS
	ANDI	T1,PAGSIZ-1		;KEEP JUST THE OFFSET INTO THE PAGE
	IOR	T1,A1			;FORM THE MAPPED ADDRESS
	AOS	MAPDAT+.MPADR		;COUNT ADDRESS COMPUTATIONS
	JRST	CPOPJ1			;AND RETURN
SUBTTL	Address mapping -- Convert virtual to physical addresses


; Convert an exec virtual "funny" address to a mapped physical address
; Call:	MOVE	PMA, physcial address of UPT
;	MOVE	VMA, exec virtual "funny" address
;	PUSHJ	P,PHYFUN
;	<NON-SKIP>			;FAILED
;	<SKIP>				;PMA:= MAPPED PHYSICAL ADDRESS
;
PHYFUN:	CAML	VMA,PPABEG		;RANGE CHECK IT
	CAML	VMA,PPAEND		;MUST BE A "FUNNY PAGE" ADDRESS
	  ERR.	(IAD,CPOPJ)		;ILLEGAL ADDRESS
	MOVEM	T1,PAGFUN		;SAVE T1
	MOVE	T1,MAPDAT+.MPPAG	;GET PAGING TYPE
	MOVE	T1,FUNTAB-1(T1)		;GET FUNNY PAGE POINTER OFFSET IN UPT
	EXCH	T1,PAGFUN		;SAVE IT AND RESTORE T1
	JRST	PHYCOM			;ENTER COMMON PHYSICAL ADDRESS CODE

; KA rel/prot:	No per-process space to map.
; KI paging:	The pointer to the first age of funny space (340) comes
;		immediately after the pointer for the user's page 777.
; KL paging:	The ADDI T1,SECTAB(T4) has to be cancelled, since
;		the pointer to page 340 is the 340th word in the
;		UPT.  TOPS-10 changes the first (and only) word of
;		the SPT to contain the address of the UPT whenever
;		a context switch occurs.
FUNTAB:	EXP	0			;KA RELOCATION AND PROTECTION REGISTERS
	EXP	<777+1>-340		;KI PAGING ON A KI10, KL10 OR KS10
	EXP	-SECTAB			;KL PAGING ON A KL10 OR KS10
	EXP	-SECTAB			;KL PAGING ON A KC10


; Convert a virtual address to a mapped physical address
; Call:	MOVE	PMA, physical address of EPT or UPT
;	MOVE	VMA, virtual address
;	PUSHJ	P,PHYADR
;	<NON-SKIP>			;FAILED
;	<SKIP>				;PMA:= MAPPED PHYSICAL ADDRESS
;
PHYADR:	SETZM	PAGFUN			;CLEAR FUNNY PAGE UPT OFFSET
PHYCOM:	PUSHJ	P,SAVT4			;SAVE T1, T2, T3, AND T4
	MOVE	T1,PMA			;GET EPT OR UPT ADDRESS
	MOVE	T2,VMA			;GET VIRTUAL ADDRESS TO CONVERT
	MOVE	T3,T2			;COPY ADDRESS
	LSH	T3,-11			;CONVERT TO PAGE NUMBER
	MOVE	T4,MAPDAT+.MPPAG	;GET PAGING TYPE
	PUSHJ	P,@PHYTAB-1(T4)		;DISPATCH TO THE PROPER PAGING ROUTINES
	  POPJ	P,			;CAN'T CONVERT VRT TO PHY ADDRESS
	MOVE	PMA,T1			;GET PHYSICAL ADDRESS
	JRST	CPOPJ1			;AND RETURN

PHYTAB:	EXP	KARPR			;KA RELOCATION AND PROTECTION REGISTERS
	EXP	KIPAG			;KI PAGING ON A KI10, KL10 OR KS10
	EXP	KLPAG			;KL PAGING ON A KL10 OR KS10
;	EXP	KCPAG			;KL PAGING ON A KC10
; Return the physical address of the boot CPU's EPT
; Call:	PUSHJ	P,PHYEPT
;	<NON-SKIP>			;FAILED
;	<SKIP>				;PMA:= PHYSICAL ADDRESS, SPT:= SPT BASE
;
PHYEPT:	MOVE	PMA,EPTADR		;GET THE EPT ADDRESS
	MOVE	SPT,PMA			;HACK FOR TOPS-10 ONE WORD SPT
	TLO	F,FL.EPM		;FLAG EXEC MAPPING TO TAKE PLACE
	JRST	CPOPJ1			;RETURN


; Return the physical address of a UPT
; Call:	MOVE	T1, job number
;	PUSHJ	P,PHYUPT
;	<NON-SKIP>			;FAILED
;	<SKIP>				;PMA:= PHYSICAL ADDRESS, SPT:= SPT BASE
;
PHYUPT:	CAMLE	T1,JOBN			;RANGE CHECK
	ERR.	(IJN,CPOPJ)		;ILLEGAL JOB NUMBER
	PUSHJ	P,SAVT1			;SAVE T1
	ADD	T1,JBTUPM		;OFFSET TO THE JOB'S UPMP ENTRY
	PUSHJ	P,EXAMINE		;READ IT
	  ERR.	(JNA,CPOPJ)		;JOB NOT ADDRESSABLE
	HRRZ	PMA,T1			;UPMP PAGE NUMBER IS A RH QUANTITY
	JUMPE	PMA,[ERR. (JSO,CPOPJ)]	;JOB SWAPPED OUT
	LSH	PMA,11			;CONVERT TO AN ADDRESS
	MOVE	SPT,PMA			;HACK FOR TOPS-10 ONE WORD SPT
	JRST	CPOPJ1			;AND RETURN
SUBTTL	Address mapping -- Copy a block of mapped data


; Copy a mapped block of data
; Call:	MOVE	T1, copy-block-address
;	PUSHJ	P,ADRCPY
;
ADRCPY:	SKIPN	A1,.CBWCT(T1)		;GET NUMBER OF WORDS TO MOVE
	POPJ	P,			;NOTHING TO DO
	CAIG	A1,2			;MOVING A WORD OR TWO?
	JRST	@[EXP	ADRC.1		;1 WORD
		  EXP	ADRC.2]-1(A1)	;2 WORDS
	JRST	ADRC.3			;MORE THAN 2 WORDS

ADRC.1:	MOVE	A2,@.CBRAD(T1)		;GET A WORD
	MOVEM	A2,@.CBWAD(T1)		;PUT A WORD
	JRST	ADRC.4			;UPDATE ADDRESSES AND RETURN

ADRC.2:	MOVE	A2,.CBRAD(T1)		;GET ADDRESS
	ADDI	A2,1			;PLUS ONE
	TRNN	A2,PAGSIZ-1		;OVERFLOW TO THE NEXT PAGE?
	SOJA	A1,ADRC.1		;YES--JUST MOVE A SINGLE WORD
	DMOVE	A2,@.CBRAD(T1)		;GET TWO WORDS
	DMOVEM	A2,@.CBWAD(T1)		;PUT TWO WORDS
	JRST	ADRC.4			;UPDATE ADDRESSES AND RETURN

ADRC.3:	HRLZ	A2,.CBRAD(T1)		;GET READ ADDRESS
	HRR	A2,.CBWAD(T1)		;GET WRITE ADDRESS
	MOVE	A3,.CBRAD(T1)		;GET READ ADDRESS AGAIN
	ADDI	A3,PAGSIZ		;ROUND UP A PAGE
	TRZ	A3,PAGSIZ-1		; BUT NOT BEYOND A PAGE BOUNDRY
	SUB	A3,.CBRAD(T1)		;GET MAXIMUM WORDS WE CAN BLT
	CAMLE	A3,A1			;TRYING TO MOVE TOO MANY WORDS?
	SKIPA	A3,A1			;YES--ONLY COPY AS MANY AS REQUESTED
	MOVE	A1,A3			;MAKE SURE THE COUNTS AGREE
	ADD	A3,.CBWAD(T1)		;COMPUTE LAST ADDRESS +1
	BLT	A2,-1(A3)		;COPY DATA

ADRC.4:	EXCH	A1,.CBWCT(T1)		;SWAP WORDS XFERED AND REQUESTED NUMBER
	SUBM	A1,.CBWCT(T1)		;UPDATE COUNT
	ADDM	A1,.CBRAD(T1)		;ADJUST SOURCE ADDRESS
	ADDM	A1,.CBWAD(T1)		;ADJUST DESTINATION ADDRESS
	POPJ	P,			;RETURN
SUBTTL	Address mapping -- KA relocation and protection


KARPR:	MOVE	T3,T1			;SAVE THE JOB NUMBER
	ADD	T1,JBTADR		;OFFSET INTO THE RELOC AND PROT TABLE
	TLNN	T2,777777		;256K ADDRESS LIMITATION ON A KA10
	PUSHJ	P,EXAMINE		;READ THE ENTRY FOR JOB'S LOW SEGMENT
	  ERR.	(JNA,CPOPJ)		;JOB NOT ADDRESSABLE
	HLRZ	T4,T1			;GET PROTECTION
	CAMG	T2,T4			;WITHIN THE LOW SEGMENT?
	JRST	KARPR3			;YES

KARPR1:	SKIPN	T1,JBTUPM		;HAVE THIS TABLE?
	JRST	KARPR2			;NO
	ADD	T1,T3			;INDEX TO THE LOW SEG ENTRY
	ADD	T1,JOBN			;INDEX TO THE HIGH SEG ENTRY
	PUSHJ	P,EXAMINE		;READ THAT WORD
	  SETZ	T1,			;CAN'T
	JUMPE	T1,[ERR. (JNA,CPOPJ)]	;JOB NOT ADDRESSABLE
	HLRZ	T4,T1			;GET THE HIGH SEGMENT ORIGIN
	TRZA	T4,PAGSIZ-1		;CLEAR ANY JUNK

KARPR2:	MOVEI	T4,400000		;USE DEFAULT HIGH SEG ORIGIN
	MOVE	T1,T3			;GET THE JOB NUMBER BACK AGAIN
	ADD	T1,JBTADR		;OFFSET INTO THE RELOC AND PROT TABLE
	ADD	T1,JOBN			;PLUS JOBN TO GET SEGMENT ENTRY
	PUSHJ	P,EXAMINE		;READ THE ENTRY FOR JOB'S HIGH SEGMENT
	  ERR.	(JNA,CPOPJ)		;JOB NOT ADDRESSABLE
	HLRZ	T3,T1			;GET HIGH SEGMENT LENGTH (PROTECTION)
	ADDI	T3,(T4)			;COMPUTE THE END OF THE SEGMENT
	CAMG	T2,T3			;ADDRESS WITHIN THE BOUNDS
	CAMGE	T2,T4			; OF THE HIGH SEGMENT?
	  ERR.	(IAD,CPOPJ)		;ILLEGAL ADDRESS
	SKIPA				;JOIN COMMON CODE

KARPR3:	MOVEI	T4,0			;LOW SEG ORIGIN IS ZERO
	TLZ	T1,777777		;KEEP ONLY PHYSICAL RELOCATION ADDRESS
	SUB	T2,T4			;SUBTRACT SEGMENT ORIGIN
	ADDI	T1,(T2)			;OFFSET TO DESIRED VIRTUAL ADDRESS
	PUSHJ	P,PADDRESS		;MAKE IT ADDRESSIBLE
	  ERR.	(JNA,CPOPJ)		;JOB NOT ADDRESSABLE
	JRST	CPOPJ1			;AND RETURN
SUBTTL	Address mapping -- KI paging


KIPAG:	TLZN	F,FL.EPM		;DOING EXEC PHYSICAL MAPPING?
	JRST	KIPAG1			;NO--UPMP DECODING
	CAIGE	T2,^D112*^D1024		;IS THE ADDRESS IN THE LOWER 112K?
	JRST	KIPAG2			;YES--THAT'S EASY
	CAIGE	T2,^D128*^D1024		;BETTER NOT BE IN FUNNY SPACE
	ERR.	(IAD,CPOPJ)		;BECAUSE THATS AN ILLEGAL ADDRESS

KIPAG1:	LDB	T3,[POINT 9,T2,26]	;GET THE TARGET PAGE NUMBER
	ADD	T3,PAGFUN		;INCLUDE FUNNY PAGE OFFSET (IF ANY)
	LSHC	T3,-1			;DIVIDE BY TWO
	ADDI	T1,(T3)			;COMPUTE UPMP INDEX
	PUSHJ	P,PEXAMINE		;READ THE UPMP ENTRY FOR THAT PAGE
	  ERR.	(JNA,CPOPJ)		;JOB NOT ADDRESSABLE
	TLNN	T4,400000		;ODD PAGE?
	MOVSS	T1			;NO--SWAP HALVES SO LDB GETS RIGHT PAGE
	LDB	T1,[POINT 13,T1,35]	;GET PAGE NUMBER OF TARGET PAGE
	LSH	T1,11			;CONVERT TO AN ADDRESS
	TDZA	T2,[-1-<PAGSIZ-1>]	;GET OFFSET INTO THE PAGE

KIPAG2:	SKIPA	T1,T2			;GET PHYSICAL EXEC ADDRESS
	ADDI	T1,(T2)			;COMPUTE PHYSICAL TARGET ADDRESS
	PUSHJ	P,PADDRESS		;MAKE IT ADDRESSIBLE
	  ERR.	(IAD,CPOPJ)		;ILLEGAL ADDRESS
	JRST	CPOPJ1			;AND RETURN
SUBTTL	Address mapping -- KL paging


KLPAG:	MOVNI	T4,2			;GET INITIAL VALUE FOR POINTER FLAG
	MOVEM	T4,PAGFLG		;SET IT
	HLRZ	T4,T2			;GET SECTION NUMBER
	CAILE	T4,MXSECN		;RANGE CHECK SECTION NUMBER
	ERR.	(IAD,CPOPJ)		;ILLEGAL ADDRESS
	ADDI	T1,SECTAB(T4)		;INDEX INTO SECTION MAP POINTERS
	SKIPN	T4,PAGFUN		;HAVE A FUNNY PAGE OFFSET?
	JRST	KLPAGM			;NO--ONWARD
	ADD	T1,PAGFUN		;INCLUDE FUNNY PAGE OFFSET (IF ANY)
	ADDI	T1,(T3)			;AND OFFSET BY THE FUNNY PAGE NUMBER
	SETZ	T3,			;SO WE DON'T DO USE IT TWICE
	AOS	PAGFLG			;SAY WE'RE POINTING TO A PAGE MAP NOW

; Decode a map entry
; If PAGFLG = -2, T1 has addr in the section map part of EPT/UPT
; If PAGFLG = -1, T1 has addr of entry in the page map for this section
; If PAGFLG =  0, T1 had the mapping for the page in question
;
; T2 has virtual address
; T3 has virtual page number
;
KLPAGM:	PUSHJ	P,PADDRESS		;COMPUTE THE ADDRESS OF A MAP ENTRY
	  ERR.	(JNA,CPOPJ)		;JOB NOT ADDRESSABLE
	AOSLE	PAGFLG			;FLAG WHAT WE'RE LOOKING AT
	JRST	 KLPAGX			;FOUND THE PAGE WE'RE LOOKING FOR
	LDB	T4,[POINT 3,(T1),2]	;GET THE ENTRY TYPE
	JRST	@KLPAGT(T4)		;DISPATCH BASED ON POINTER TYPE

KLPAGT:	EXP	KLPAG0			;(0) NO ACCESS
	EXP	KLPAG1			;(1) IMMEDIATE
	EXP	KLPAG2			;(2) SHARED
	EXP	KLPAG3			;(3) INDIRECT
	EXP	KLPAGE			;(4) ILLEGAL
	EXP	KLPAGE			;(5) ILLEGAL
	EXP	KLPAGE			;(6) ILLEGAL
	EXP	KLPAGE			;(7) ILLEGAL


KLPAGX:	ANDI	T2,PAGSIZ-1		;GET JUST THE INDEX INTO THE PAGE
	ADDI	T1,(T2)			;GET TARGET ADDRESS TO EXAMINE
	JRST	CPOPJ1			;RETURN


KLPAGE:	ERR.	(UPC,CPOPJ)		;UNIMPLEMENTED KL PAGING CODE
; KL paging code 0 - No access
;
KLPAG0:	ERR.	(NAP,CPOPJ)		;NO ACCESS TO REQUESTED PAGE


; KL paging code 1 - Immediate
;
KLPAG1:	MOVE	T1,(T1)			;GET POINTER
	TLNE	T1,77			;STORAGE MEDIUM NON-ZERO? (TOPS20)
	ERR.	(PNC,CPOPJ)		;PAGE NOT IN CORE
	ANDI	T1,17777		;KEEP JUST THE PAGE MAP PAGE NUMBER
	LSH	T1,11			;CONVERT TO AN ADDRESS
	SKIPN	PAGFLG			;POINTING TO A PAGE MAP FOR A SECTION?
	JRST	KLPAGM			;NO--LOOP BACK AND DECODE MAP POINTER
	ANDI	T3,777			;KEEP ONLY RELATIVE PAGE # IN SECTION
	ADDI	T1,(T3)			;INDEX INTO PAGE MAP FOR TARGET PAGE
	SETZ	T3,			;CLEAR FOR NEXT TIME
	JRST	KLPAGM			;LOOP BACK AND DECODE MAP POINTER


; KL paging code 2 - Shared
;
KLPAG2:	HRRZ	T1,(T1)			;GET INDEX INTO THE SPT
	CAIE	T1,0			;RANGE CHECK
	ERR.	(SIR,CPOPJ)		;SPT INDEX OUT OF RANGE
	ADD	T1,SPT			;OFFSET
	SETOM	PAGFLG			;STILL LOOKING AT A PAGE MAP
	JRST	KLPAGM			;LOOP BACK AND DECODE MAP POINTER


; KL paging code 3 - Indirect
;
KLPAG3:	LDB	T4,[POINT 9,(T1),17]	;GET INDEX INTO SECONDARY PAGE MAP
	HRRZ	T1,(T1)			;GET INDEX INTO THE SPT
	CAIE	T1,0			;RANGE CHECK
	ERR.	(SIR,CPOPJ)		;SPT INDEX OUT OF RANGE
	ADD	T1,SPT			;OFFSET
	ADDI	T1,(T4)			;OFFSET INTO THE SECONDARY PAGE MAP
	SETOM	PAGFLG			;STILL LOOKING AT A PAGE MAP
	JRST	KLPAGM			;LOOP BACK AND DECODE MAP POINTER
SUBTTL	Address mapping -- Dispatch tables


; Initialization
;
INITAB:	EXP	MONINI			;MONITOR 
	EXP	JOBINI			;JOB 
	EXP	FILINI			;FILE 


; Page creation
;
CRETAB:	EXP	MONCRE			;MONITOR
	EXP	JOBCRE			;JOB
	EXP	FILCRE			;FILE


; Page destruction
;
DESTAB:	EXP	MONDES			;MONITOR
	EXP	JOBDES			;JOB
	EXP	FILDES			;FILE


; Deposit
;
DEPTAB:	EXP	MONDEP			;MONITOR
	EXP	JOBDEP			;JOB
	EXP	FILDEP			;FILE


; Mapping code names
;
CODTAB:	[ASCIZ	|monitor|]		;MONITOR
	[ASCIZ	|job|]			;JOB
	[ASCIZ	|file|]			;FILE


; Convert virtual to physical address
;
CVTTAB:	EXP	MONCVT			;MONITOR
	EXP	JOBCVT			;JOB
	EXP	FILCVT			;FILE
SUBTTL	Address mapping -- Monitor


; Here at initialization to setup the page tables
;
MONINI:	TLNE	F,FL.EXE		;CHECK FOR ILLEGAL FLAGS
	ERR.	(CMF,CPOPJ)		;CONFLICTING MAPPING CODE AND FLAGS
	JRST	CPOPJ1			;RETURN


; Here to create a SPY page
; Call:	MOVE	A2, cache chunk address
;	PUSHJ	P,MONCRE
;	<NON-SKIP>			;SPY PAGE CREATE FAILED
;	<SKIP>				;PAGE CREATED
;
MONCRE:	PUSHJ	P,SAVT2			;SAVE T1 AND T2
	MOVE	T1,.CBPRC(A2)		;GET PROCESS PAGE NUMBER TO MAP
	MOVE	T2,.CBUSR(A2)		;GET USER PAGE NUMBER TO MAP INTO
	PUSHJ	P,PAGSPY		;CREATE A SPY PAGE
	  POPJ	P,			;CAN'T
	MOVE	T1,.CBFLG(A2)		;GET FLAGS
	TLO	T1,(CB.CRE)		;PAGE WAS JUST CREATED
	TLNE	F,FL.PPM!FL.TPP		;PHYSICAL PAGE MAPPING?
	TLO	T1,(CB.PHY)		;YES
	MOVEM	T1,.CBFLG(A2)		;UPDATE FLAGS
	JRST	CPOPJ1			;RETURN
; Here to destroy a page
; Call:	MOVE	A2, cache chunk address
;	PUSHJ	P,MONDES
;	<NON-SKIP>			;DESTROY FAILED
;	<SKIP>				;USER PAGE DESTROYED
;
MONDES:	PUSHJ	P,SAVT2			;VE T1 AND T2
	MOVSI	T2,(CB.CRE)		;GET PAGE CREATED BIT
	TDNN	T2,.CBFLG(A2)		;HAVE A PAGE THERE?
	POPJ	P,			;NO
	MOVE	T1,.CBUSR(A2)		;GET THE USER PAGE NUMBER
	PUSHJ	P,PAGDES		;DESTROY IT
	  POPJ	P,			;CAN'T
	MOVSI	T2,(CB.CRE!CB.PHY)	;GET SOME BITS
	ANDCAM	T2,.CBFLG(A2)		;CLEAR THEM
	JRST	CPOPJ1			;RETURN


; Here to deposit a word in the running monitor. The arguments are
; nicely setup for the POKE. UUO and validity checking has already
; been done, so there's little to do.
; Call:	MOVE	T1, mapped address
;	MOVE	T2, old contents
;	MOVE	T3, new contents
;	PUSHJ	P,MONDEP
;
MONDEP:
; *** TURN OFF PHYSICAL POKE FOR NOW ***
;	TLNN	F,FL.PPM		;PHYSICAL PAGE MAPPING?
	TDZA	T2,T2			;MONITOR VIRTUAL ADDRESSING
	MOVEI	T2,UU.PHY		;PHYSICAL CORE ADDRESSING
	MOVE	T1,[3,,POKBLK]		;SET UP UUO
	TLNE	F,FL.PAT		;PATCHING?
	POKE.	T1,(T2)			;WRITE A WORD
	  ERR.	(,CPOPJ)		;POKE. UUO FAILURE
	JRST	CPOPJ1			;RETURN


; Test if conversion from virtual to physical address is needed
; Call:	PUSHJ	P,MONCVT
;	<NON-SKIP>			;NO CONVERSION NECESSARY
;	<SKIP>				;CONVERT
;
MONCVT:	POPJ	P,			;NEVER CONVERT
SUBTTL	Address mapping -- Job


; Here at initialization to validate arguments and pick up the
; job number.
;
JOBINI:	TLNN	F,FL.PPM!FL.EXE		;CHECK FOR ILLEGAL FLAGS
	ERR.	(CMF,CPOPJ)		;CONFLICTING MAPPING CODE AND FLAGS
	MOVE	T1,USRACS+.AP		;GET ARGUMENT
	SKIPG	T1,.MPARG(T1)		;GET JOB NUMBER
	ERR.	(IJN,CPOPJ)		;ILLEGAL JOB NUMBER
	MOVEM	T1,USRJOB		;WHICH IS THE JOB NUMBER FOR JOB MODE
	JRST	CPOPJ1			;RETURN


; Here to create a page and map in one page from the target job
; Call:	MOVE	A2, index into page tables
;	PUSHJ	P,JOBCRE
;	<NON-SKIP>		;COULDN'T MAP PAGE
;	<SKIP>			;PAGE MAPPED
;
JOBCRE:	TLNE	F,FL.PPM!FL.TPP		;PHYSICAL PAGE MAPPING?
	POPJ	P,			;CAN'T DO THAT FOR A JOB
	PUSHJ	P,SAVT2			;SAVE T1 AND T2
	MOVSI	T1,(CB.CRE)		;GET A BIT
	TDNE	T1,.CBFLG(A2)		;HAS A PAGE BEEN CREATED?
	JRST	JOBC.1			;YES
	MOVE	T1,.CBUSR(A2)		;GET A OUR PAGE NUMBER
	PUSHJ	P,PAGACC		;CHECK PAGE ACCESSIBILITY
	  SKIPA				;NOT THERE
	JRST	JOBC.1			;ONWARD
	PUSHJ	P,PAGCRE		;DO IT
	  POPJ	P,			;CAN'T

JOBC.1:	MOVSI	T2,(CB.CRE)		;GET A BIT
	IORM	T2,.CBFLG(A2)		;MARK PAGE AS BEING CREATED

JOBC.2:	HRLZ	T1,USRJOB		;GET JOB NUMBER
	HRRI	T1,PAGSIZ		;WANT A WHOLE PAGE
	MOVEM	T1,UUOARG+0		;SAVE IT
	MOVE	T1,.CBUSR(A2)		;GET OUR PAGE NUMBER
	HRL	T1,.CBPRC(A2)		;GET PAGE WE'RE MAPPING
	LSH	T1,11			;CONVERT TO MAPPED ADDR,,USER ADDR
	MOVEM	T1,UUOARG+1		;SAVE IT
	MOVEI	T1,UUOARG		;SET UP UUO
	JOBPEK	T1,			;MAP THE JOB'S PAGE INTO OURS
	  ERR.	(,CPOPJ)		;JOBPEK UUO FAILURE
	PUSHJ	P,JOBDES		;ZAP THE PAGE TABLE ENTRIES
	  JFCL				;CAN'T FAIL
	JRST	CPOPJ1			;RETURN
; All that is needed to invalidate a mapped job page is to
; zap a couple of entries. It would be counterproductive
; to actually destroy the pages in question.
;
JOBDES:	PUSHJ	P,SAVT1			;SAVE T1
	MOVSI	T1,(CB.CRE)		;GET THE CREATED BIT
	ANDCAM	T1,.CBFLG(A2)		;CLEAR IT
	JRST	CPOPJ1			;RETURN


JOBDEP:	TLNN	F,FL.PAT		;PATCHING?
	POPJ	P,			;NO
	HRLZ	T4,USRJOB		;GET THE JOB NUMBER
	TLO	T4,(JK.WRT)		;LITE THE WRITE BIT
	HRRI	T4,1			;WRITE ONLY ONE WORD
	MOVEM	T4,UUOARG+0		;SAVE FLAG WORD
	MOVSI	T4,POKBLK+2		;WORD TO WRITE IS IN POKBLK+2
	HRR	T4,POKBLK+0		;GET USER VIRTUAL ADDRESS FOR JOB
	MOVEM	T4,UUOARG+1		;SAVE IT
	MOVEI	T4,UUOARG		;SET UP UUO
	JOBPEK	T4,			;WRITE THAT JOB'S CORE IMAGE
	  ERR.	(,CPOPJ)		;JOBPEK UUO FAILURE
	JRST	JOBDES			;INVALIDATE THAT PAGE AND RETURN


; Test if conversion from virtual to physical address is needed
; Call:	PUSHJ	P,JOBCVT
;	<NON-SKIP>			;NO CONVERSION NECESSARY
;	<SKIP>				;CONVERT
;
JOBCVT:	POPJ	P,			;NEVER CONVERT
SUBTTL	Address mapping -- File


FILINI:	MOVE	T1,USRACS+.AP		;GET USER'S ARG POINTER
	MOVE	T1,.MPARG(T1)		;GET ADDRESS OF FILESPEC
	PUSHJ	P,FILOPN		;OPEN THE FILE
	  ERR.	(MIF,CPOPJ)		;MAPPER INITIALIZATION FAILURE
	TLNN	F,FL.EXE		;EXE FILE MAPPING?
	JRST	CPOPJ1			;NO - ALL DONE
	PUSHJ	P,EXEDIR		;LOAD .EXE DIRECTORY INTO CORE
	  ERR.	(MIF,CPOPJ)		;MAPPER INITIALIZATION FAILURE
	JRST	CPOPJ1			;RETURN


; Here to create a page and map in one page from a file
; Call:	MOVE	A2, index into page tables
;	PUSHJ	P,FILCRE
;	<NON-SKIP>		;COULDN'T MAP PAGE
;	<SKIP>			;PAGE MAPPED
;
FILCRE:	PUSHJ	P,SAVT4			;SAVE T1, T2, T3, AND T4
	MOVSI	T1,(CB.PHY)		;GET PHYSICAL BIT
	TLNE	F,FL.PPM!FL.TPP		;DOING SOME FLAVOR OF PHYSICAL MAPPING?
	IORM	T1,.CBFLG(A2)		;YES
	TLZ	F,FL.TPP		;CLEAR TEMPORARY PHYSICAL PAGE MAPPING
	MOVE	T1,.CBUSR(A2)		;GET PAGE IN QUESTION
	PUSHJ	P,PAGCHK		;DOES IT EXIST
	  POPJ	P,			;NO--AND WE CAN'T CREATE IT
	MOVSI	T1,(CB.CRE)		;GET A BIT
	IORM	T1,.CBFLG(A2)		;REMEMBER WE JUST CREATED THE PAGE
	MOVE	T1,.CBPRC(A2)		;GET PROCESS PAGE NUMBER
	PUSHJ	P,EXEPAG		;FIND THE FILE PAGE NUMBER
	  POPJ	P,			;CAN'T
	LSH	T1,2			;MULTIPLY TIMES 4 TO GET BLOCK NUMBER
	TLNN	F,FL.SIO		;SUPER I/O?
	ADDI	T1,1			;NO - ADJUST BLOCK NUMBER
	PUSHJ	P,FILIPS		;POSITION FOR INPUT
	  POPJ	P,			;CAN'T
	MOVE	T1,.CBUSR(A2)		;GET OUR PAGE NUMBER
	LSH	T1,11			;COMVERT TO AN ADDRESS
	SUBI	T1,1			;-1
	HRLI	T1,-PAGSIZ		;MAKE AN IOWD
	MOVEM	T1,IOLIST		;SAVE IT
	PUSHJ	P,FILRED		;READ THE PAGE
	  POPJ	P,			;CAN'T
	JRST	CPOPJ1			;RETURN
; Here to destroy a page
; Call:	MOVE	A2, index into page tables
;	PUSHJ	P,MONDES
;	<NON-SKIP>		;DESTROY FAILED
;	<SKIP>			;USER PAGE DESTROYED
;
FILDES:	PUSHJ	P,SAVT1			;SAVE T1
	MOVSI	T1,(CB.CRE)		;GET A BIT
	TDNN	T1,.CBFLG(A2)		;PAGE MUST EXIST
	  POPJ	P,			;LOSE
	MOVE	T1,.CBUSR(A2)		;GET OUR PAGE NUMBER
	PUSHJ	P,PAGDES		;DESTROY IT
	  POPJ	P,			;CAN'T
	MOVSI	T1,(CB.CRE)		;GET THE CREATED BIT
	ANDCAM	T1,.CBFLG(A2)		;CLEAR IT
	JRST	CPOPJ1			;RETURN


FILDEP:	TLNN	F,FL.PAT		;PATCHING?
	POPJ	P,			;NO
	HALT	.


; Test if conversion from virtual to physical address is needed
; Call:	PUSHJ	P,FILCVT
;	<NON-SKIP>			;NO CONVERSION NECESSARY
;	<SKIP>				;CONVERT
;
FILCVT:	TLNN	F,FL.GTS		;GETTABS SETUP?
	POPJ	P,			;NOT A MONITOR IF NO GETTABS SIMULATION
	SKIPE	HIORG			;SKIP IF WE DON'T KNOW THE HISEG ORIGIN
	CAMGE	T1,HIORG		;BELOW THE HIGH SEG ORIGIN?
	JRST	FILC.1			;YES
	SKIPE	HIFLAG			;HIGH SEGMENT MAPPED?
	AOS	(P)			;YES--DECODE PAGE MAP
	POPJ	P,			;ELSE TREAT AS A PHYSICAL REFERENCE

FILC.1:	CAMLE	T1,HGHUEA		;BEYOND HIGHEST UNMAPPED EXEC ADDRESS?
	AOS	(P)			;NEED TO CONVERT
	POPJ	P,			;RETURN
SUBTTL	Cache management -- Clear out the cache


; This routine must be called at the start of cache initialization.
; It will attempt to destroy any pages available for caching so
; we can get a fresh start.
;
CSHCLR:	MOVE	A1,MAPDAT+.MPCPN	;GET FIRST PAGE NUMBER
	MOVE	A2,PAGCNT		;GET COUNT OF AVAILABLE PAGES

CSHC.1:	MOVE	T1,A1			;LOAD A PAGE NUMBER
	PUSHJ	P,PAGACC		;DOES THE PAGE EXIST?
	  SKIPA				;NO
	PUSHJ	P,PAGDES		;DESTROY IT
	  JFCL				;MAYBE THE PAGE WASN'T THERE
	ADDI	A1,1			;ADVANCE PAGE NUMBER
	SOJG	A2,CSHC.1		;LOOP FOR ALL PAGES
	POPJ	P,			;AND RETURN
SUBTTL	Cache management -- Map the cache


; This routine will dynamically allocate the hash table
; and chunks out of the pages allotted for mapping.  It is
; also responsible for setting and/or adjusting the count
; of available pages for caching and the starting page to
; cache.
;
CSHMAP:	MOVE	A1,MAPDAT+.MPCPN	;GET FIRST PAGE NUMBER TO USE
	LSH	A1,11			;CONVERT TO AN ADDRESS
	MOVEM	A1,HASHTA		;SAVE HASH TABLE ADDRESS
	MOVE	A1,PAGCNT		;GET NUMBER OF PAGES TO CACHE
	LSH	A1,2			;MULTIPLY BY 4 TO GET HASH TABLE SIZE
	MOVEM	A1,HASHTL		;SAVE LENGTH OF HASH TABLE
	ADD	A1,HASHTA		;GET LAST ADDRESS IN HASH TABLE
	MOVEM	A1,HASHCA		;SAVE AS ADDRESS OF FIRST CHUNK

	MOVE	A2,PAGCNT		;GET NUMBER OF PAGES TO CACHE
	IMULI	A2,.CBLEN		;GET WORDS NEEDED FOR CHUNKS
	ADDI	A1,(A2)			;TOTAL UP WORDS NEEDED
	MOVE	A2,A1			;COPY NUMBER OF WORDS
	SUB	A1,HASHCA		;GET LENGTH OF CHUNK AREA
	MOVEM	A1,HASHCL		;SAVE IT

	TRZE	A2,PAGSIZ-1		;ON A PAGE BOUNDRY?
	ADDI	A2,PAGSIZ		;ROUND UP
	LSH	A2,-11			;GET FIRST AVAILABLE PAGE FOR MAPPING
	MOVEM	A2,CSHPAG		;SAVE IT
	SUB	A2,MAPDAT+.MPCPN	;GET PAGES USED FOR TABLE AND CHUNKS
	MOVN	A3,A2			;GET NEGATIVE COUNT
	CAML	A2,PAGCNT		;HAVE ENOUGH AVAILABLE?
	ERR.	(HAF,CPOPJ)		;HASH TABLE ALLOCATION FAILURE
	EXCH	A2,PAGCNT		;SWAP
	SUBM	A2,PAGCNT		;UPDATE NEW NUMBER OF PAGES AVAILABLE
	IMULI	A3,.CBLEN		;GET WORDS TO TRIM
	ADDM	A3,HASHCL		;ADJUST LENGTH OF CHUNK AREA
	MOVE	A1,HASHTA		;GET ADDRESS OF HASH TABLE
	LSH	A1,-11			;CONVERT TO A PAGE NUMBER
	MOVE	A2,CSHPAG		;GET FIRST PAGE TO CACHE
	SUB	A2,A1			;GET NUMBER OF PAGES TO CREATE

CSHM.1:	MOVE	T1,A1			;GET A PAGE NUMBER
	PUSHJ	P,PAGACC		;DOES THE PAGE ALREADY EXIST?
	  SKIPA				;NOT THERE
	JRST	CSHM.2			;ON TO THE NEXT PAGE
	PUSHJ	P,PAGCRE		;CREATE IT
	  ERR.	(HAF,CPOPJ)		;HASH TABLE ALLOCATION FAILURE

CSHM.2:	ADDI	A1,1			;POINT TO NEXT PAGE
	SOJG	A2,CSHM.1		;LOOP FOR ALL PAGES
	JRST	CPOPJ1			;RETURN
SUBTTL	Cache management -- Set up the hash tables and links


;Call:	PUSHJ	P,CSHINI
;	<return>
;
CSHINI:	MOVE	A1,HASHTA		;GET STARTING ADDRESS OF HASH TABLE
	SKIPA	A2,HASHTL		;GET LENGTH OF HASH TABLE

; Link all hash entries to themselves
CSHI.1:	ADDI	A1,2			;ADDRESS OF SELF
	MOVEM	A1,.CBNHB(A1)		;STORE NEXT
	MOVEM	A1,.CBPHB(A1)		;AND PREVIOUS TO SELF
	SUBI	A2,1			;ADVANCE TO NEXT
	SOJG	A2,CSHI.1		;AND LOOP FOR ALL

; Link header entry links to themselves
	MOVEI	A1,CBHEAD		;ADDRESS OF HEADER
	MOVEM	A1,CBHEAD+.CBNAB	;STORE NEXT
	MOVEM	A1,CBHEAD+.CBPAB	;AND PREVIOUS TO SELF
	MOVEM	A1,CBHEAD+.CBNHB	;STORE NEXT IN INVALID LIST
	MOVEM	A1,CBHEAD+.CBPHB	;AND PREVIOUS TO SELF

	MOVE	A1,HASHCA		;POINT TO START OF CHUNKS
	MOVE	A2,CSHPAG		;GET STARTING PAGE FOR CACHING
	MOVE	A3,PAGCNT		;GET COUNT OF PAGES TO CACHE
	MOVSI	A4,(CB.AVA)		;GET CHUNK AVAILABLE BIT

CSHI.2:	MOVEM	A2,.CBUSR(A1)		;SAVE PAGE NUMBER FOR THIS CHUNK
	MOVEM	A4,.CBFLG(A1)		;MARK CHUNK AVAILABLE
	MOVE	T1,.CBUSR(A1)		;GET A PAGE NUMBER
	ADDI	A1,.CBLEN		;POINT TO NEXT CHUNK
	ADDI	A2,1			;ADVANCE TO NEXT PAGE NUMBER
	SOJG	A3,CSHI.2		;LOOP
	POPJ	P,			;RETURN
SUBTTL	Cache management -- Set cache size


; Change the cache size.  This routine will increase
; or decrease the size of the cache on the fly.
; Call:	MOVE	A1, size of cache
;	PUSHJ	P,CSHSIZ
;	  <error>			;Cant allocate more space
;	<normal>			;cache expanded/contracted
;
CSHSIZ:	SKIPGE	A1			;NEGATIVE SIZE IS BAD
	ERR.	(ICS,CPOPJ)		;ILLEGAL CACHE SIZE REQUESTED
	PUSHJ	P,SAVT1			;SAVE T1
	MOVE	T1,A1			;COPY SIZE
	SUB	T1,PAGCNT		;MINUS CURRENT SIZE
	JUMPE	T1,CPOPJ1		;RETURN IF NO CHANGE
	JUMPG	T1,CSHS.2		;EXPAND CACHE

CSHS.1:	PUSHJ	P,CSHDEA		;DEALLOCATE A CHUNK
	AOJL	T1,CSHS.1		;LOOP FOR ALL
	JRST	CSHS.3			;AND EXIT

CSHS.2:	PUSHJ	P,CSHALC		;ALLOCATE A CHUNK
	  ERR.	(NFC,CPOPJ)		;NO FREE CHUNKS FOR CACHE
	SOJG	T1,CSHS.2		;LOOP FOR ALL

CSHS.3:	MOVE	T1,PAGCNT		;GET UPDATED CACHED PAGE COUNT
	MOVEM	T1,MAPDAT+.MPCPC	;TELL THE CALLER
	JRST	CPOPJ1			;RETURN
SUBTTL	Cache management -- Allocate a chunk for the cache


; Call:	PUSHJ	P,CSHALC
;	 <error>			;Cant allocate another chunk
;	<normal>			;another chunk allocated
;
CSHALC:	MOVE	A2,HASHCA		;POINT TO START OF CHUNKS
	MOVE	A3,HASHCL		;GET LENGTH OF CHUNK AREA
	MOVSI	A4,(CB.AVA)		;GET THE AVAILABLE CHUNK BIT

CSHA.1:	TDNE	A4,.CBFLG(A2)		;CHUNK FREE?
	JRST	CSHA.2			;YES
	ADDI	A2,.CBLEN		;POINT TO NEXT CHUNK
	SUBI	A3,.CBLEN		;COUNT
	JUMPG	A3,CSHA.1		;LOOP 'TIL WE FIND ONE
	POPJ	P,			;LOSE

CSHA.2:	ANDCAM	A4,.CBFLG(A2)		;NO LONGER FREE
	AOS	PAGCNT			;COUNT CHUNKS INSERTED

;Link new chunk at beginning of "free" hash list
	MOVE	A3,CBHEAD+.CBNHB	;GET FORWARD FROM HEADER
	MOVE	A4,.CBPHB(A3)		;AND PREVIOUS FROM TOP
	MOVEM	A2,CBHEAD+.CBNHB	;INSERT US AT THE TOP
	MOVEM	A2,.CBPHB(A3)		;PREVIOUS OF OLD TOP IS US
	MOVEM	A3,.CBNHB(A2)		;NEXT OF US IS OLD TOP
	MOVEM	A4,.CBPHB(A2)		;PREVIOUS OF US IS HEADER

;Clear out any trash
	SETZM	.CBPRC(A2)		;CLEAR PROCESS PAGE NUMBER

;Link new chunk at end of accessed list
	MOVE	A3,CBHEAD+.CBPAB	;GET FORWARD FROM HEADER
	MOVE	A4,.CBNAB(A3)		;AND NEXT FROM TOP
	MOVEM	A2,CBHEAD+.CBPAB	;INSERT US AT THE TOP
	MOVEM	A2,.CBNAB(A3)		;NEXT OF OLD TOP IS US
	MOVEM	A3,.CBPAB(A2)		;PREVIOUS OF US IS OLD TOP
	MOVEM	A4,.CBNAB(A2)		;NEXT OF US IS HEADER

	JRST	CPOPJ1			;AND SKIP RETURN
SUBTTL	Cache management -- Deallocate a page from the cache


; Call:	PUSHJ	P,CSHDEA
;	<return>
;
CSHDEA:

; Delete from access chunk chain
	MOVE	A2,CBHEAD+.CBPAB	;LAST CHUNK IN CACHE
	MOVE	A3,.CBNAB(A2)		;GET NEXT
	MOVE	A4,.CBPAB(A2)		;GET PREVIOUS
	MOVEM	A3,.CBNAB(A4)		;REMOVE FROM FORWARD CHAIN
	MOVEM	A4,.CBPAB(A3)		;REMOVE FROM PREVIOUS CHAIN

;Delete from hash chain
	MOVE	A3,.CBNHB(A2)		;GET NEXT
	MOVE	A4,.CBPHB(A2)		;GET PREVIOUS
	MOVEM	A3,.CBNHB(A4)		;REMOVE FROM FORWARD CHAIN
	MOVEM	A4,.CBPHB(A3)		;REMOVE FROM PREVIOUS CHAIN

;Return core, fix up cache size
	MOVE	A3,.CBFLG(A2)		;GET THE FLAG WORD
	TLZE	A3,(CB.CRE)		;PAGE REALLY EXIST?
	PUSHJ	P,@DESTAB(F)		;YES--DESTROY IT
	  JFCL
	TLO	A3,(CB.AVA)		;MARK CHUNK AVAILABLE
	MOVEM	A3,.CBFLG(A2)		;UPDATE FLAG WORD
	SOS	PAGCNT			;CACHE IS 1 CHUNK SMALLER
	POPJ	P,			;AND RETURN
SUBTTL	Cache management -- Find an entry in the cache


; Call:	MOVE	A1, page number
;	PUSHJ	P,CSHFND
;	 <error>		;page not in cache T2/ address to insert
;	<normal>		;page in cache     T2/ address of entry
;
CSHFND:	

; Hash page number to initial entry in table
	MOVE	A4,HASHTL		;GET HASH TABLE LENGTH
	LSH	A4,-1			;DIVIDE BY 2
	MOVE	A2,A1			;COPY PAGE NUMBER
	IDIV	A2,A4			;HASH INTO TABLE
	LSH	A3,1			;DOUBLE REMAINDER
	MOVE	A4,HASHTA		;GET HASH TABLE ADDRESS
	ADDI	A4,(A3)			;INDEX INTO IT
	MOVE	A2,A4			;COPY POINTER TO START
	AOS	MAPDAT+.MPHSF		;COUNT HASH TABLE SEARCHES
	TLNN	F,FL.PPM!FL.TPP		;PHYSICAL PAGE MAPPING?
	SKIPA	A3,[TDNN A3,.CBFLG(A2)]	;GET TEST IF PHYSICAL BIT MUST BE OFF
	MOVE	A3,[TDNE A3,.CBFLG(A2)]	;GET TEST IF PHYSICAL BIT MUST BE ON
	MOVEM	A3,CSHXCT		;SAVE IT
	MOVSI	A3,(CB.PHY)		;GET THE PHYSICAL BIT

; Loop through hash chain from initial probe
;
CSHF.1:	CAMN	A4,.CBNHB(A2)		;SEE IF LOOPED AROUND
	POPJ	P,			;YES--NOT IN TABLE
	MOVE	A2,.CBNHB(A2)		;COPY CURRENT PAGE
	XCT	CSHXCT			;TEST FOR PHYSICAL PAGE
	CAME	A1,.CBPRC(A2)		;MATCH THE PROCESS PAGE NUMBER?
	SKIPA
	JRST	CPOPJ1			;FOUND IT--RETURN
	AOS	MAPDAT+.MPHSC		;WRONG PAGE--COUNT COLLISIONS
	JRST	CSHF.1			;AND LOOP
SUBTTL	Cache management -- Insert (replace) a new page in the cache


; Call:	MOVE	A1, page number
;	MOVE	A2, entry to add after
;	PUSHJ	P,CSHINS
;	<return>
;
CSHINS:	CAMN	A2,CBHEAD+.CBPAB	;SAME AS ENTRY WE FIDDLE
	JRST	[MOVEM	A1,.CBPRC(A2)	;SAVE NEW PROCESS PAGE NUMBER
		 JRST	CSHMRU]		;AND MOVE TO TOP

; Store page number, replace last page in access chain
	PUSH	P,A2			;SAVE ENTRY TO ADD
	MOVE	A2,CBHEAD+.CBPAB	;GET LAST IN CHAIN

;Unlink from old hash chain
	MOVE	A3,.CBNHB(A2)		;GET NEXT
	MOVE	A4,.CBPHB(A2)		;GET PREVIOUS
	MOVEM	A3,.CBNHB(A4)		;REMOVE FROM FORWARD CHAIN
	MOVEM	A4,.CBPHB(A3)		;REMOVE FROM PREVIOUS CHAIN

;Link this chunk into correct hash chain
	MOVE	A1,A2
	POP	P,A2			;RESTORE ENTRY TO ADD
	MOVE	A4,.CBNHB(A2)		;AND NEXT LINK
	MOVEM	A1,.CBNHB(A2)		;INSERT AFTER PREVIOUS
	MOVEM	A1,.CBPHB(A4)		;AND AS PREVIOUS OF OLD
	MOVEM	A2,.CBPHB(A1)		;STORE PREVIOUS OF OLD AS OURS
	MOVEM	A4,.CBNHB(A1)		;STORE NEXT OF OLD AS OURS
	MOVE	A2,A1

	JRST	CSHMRU			;AND MOVE ENTRY TO TOP OF LIST
SUBTTL	Cache management -- Move entry to top of list


; Call:	MOVE	A2, entry to move
;	PUSHJ	P,CSHMRU
;	<return>
;
CSHMRU:	CAMN	A2,CBHEAD+.CBNAB	;WE AT THE TOP?
	 POPJ	P,			;YES--SAVE SOME WORK

; Delete from current access chain position
	MOVE	A3,.CBNAB(A2)		;GET NEXT
	MOVE	A4,.CBPAB(A2)		;GET PREVIOUS
	MOVEM	A3,.CBNAB(A4)		;REMOVE FROM FORWARD CHAIN
	MOVEM	A4,.CBPAB(A3)		;REMOVE FROM PREVIOUS CHAIN

; Relink into "most recently used" position
	MOVE	A3,CBHEAD+.CBNAB	;GET FORWARD FROM HEADER
	MOVE	A4,.CBPAB(A3)		;AND PREVIOUS FROM TOP
	MOVEM	A2,CBHEAD+.CBNAB	;INSERT US AT THE TOP
	MOVEM	A2,.CBPAB(A3)		;PREVIOUS OF OLD TOP IS US
	MOVEM	A3,.CBNAB(A2)		;NEXT OF US IS OLD TOP
	MOVEM	A4,.CBPAB(A2)		;PREVIOUS OF US IS HEADER

	POPJ	P,			;AND RETURN
SUBTTL	Text I/O -- Character


; Input a character converting tabs to spaces and lower to upper case
; Call:	PUSHJ	P,TYI
;	<RETURN>			;T1:= CHARACTER
;
TYI:	ILDB	T1,BYTPTR		;GET A CHARACTER
	CAIN	T1,"I"-100		;TAB?
	MOVEI	T1," "			;YES - CONVERT TO A SPACE
	CAIG	T1,"Z"+40		;CHECK FOR A LOWER CASE
	CAIGE	T1,"A"+40		; CHARACTER THAT NEEDS TO BE
	  SKIPA				;  CONVERTED TO AN UPPER CASE
	TRZ	T1," "			;   CHARACTER
	POPJ	P,			;RETURN


; Output a character
; Call:	MOVE	T1, character
;	PUSHJ	P,TYO
;	<RETURN>
;
TYO:	SKIPN	BYTPTR			;OUTPUT TO TTY?
	JRST	[OUTCHR T1		;YES
		 POPJ	P,]		;RETURN
	SOSLE	BYTCNT			;COUNT CHARACTERS
	IDPB	T1,BYTPTR		;SAVE CHARACTER
	POPJ	P,			;RETURN
SUBTTL	Text I/O -- ASCIZ


; Output an ASCIZ string
; Call:	MOVE	T1, string address
;	PUSHJ	P,TSTRG
;	<RETURN>
;
TSTRG:	HRLI	T1,(POINT 7,)		;MAKE A BYTE POINTER
	PUSH	P,T1			;SAVE IT

TSTR.1:	ILDB	T1,(P)			;GET A CHARACTER
	JUMPE	T1,TSTR.2		;DONE?
	PUSHJ	P,TYO			;TYPE IT
	JRST	TSTR.1			;LOOP

TSTR.2:	POP	P,T1			;PHASE STACK
	POPJ	P,			;RETURN
SUBTTL	Text I/O -- Sixbit


; Input a possibly quoted sixbit word
; Call:	PUSHJ	P,SIXIN
;	<RETURN>			;T1:= WORD, T2:= TERMINATING CHARACTER
;
SIXIN:	MOVE	T2,[POINT 6,T3]		;GET BYTE POINTER TO ATOM BUFFER
	PUSH	P,[0]			;RESERVE A WORD
	SETZ	T3,			;CLEAR RESULT
	PUSHJ	P,FLUSH			;FLUSH LEADING SPACES AND TABS
	CAIN	T1,"#"			;WANTS TO INPUT IN OCTAL?
	JRST	OCTIN			;YES
	SKIPA				;ANALYZE CHARACTER

SIXI.1:	PUSHJ	P,TYI			;GET A CHARACTER
	CAIN	T1,""""			;QUOTE CHARACTER?
	JRST	SIXI.2			;YES
	SKIPE	(P)			;QUOTING?
	JUMPN	T1,SIXI.4		;ALL CHARACTERS ARE LEGAL
	JRST	SIXI.3			;NO

SIXI.2:	PUSHJ	P,TYI			;GET NEXT CHARACTER
	CAIN	T1,""""			;ANOTHER QUOTE?
	JRST	SIXI.4			;SAVE IT
	SETCMM	(P)			;NO - TOGGLE QUOTE FLAG
	SKIPE	(P)			;QUOTING?
	JRST	SIXI.4			;YES

SIXI.3:	CAIL	T1,"0"			;RANGE
	CAILE	T1,"9"			; CHECK
	CAIL	T1,"A"			;  THE
	CAILE	T1,"Z"			;   CHARACTER
	JRST	SIXI.5			;NOT A GOOD CHARACTER

SIXI.4:	TLNE	T2,77			;WORD FULL YET?
	JRST	SIXI.1			;YES - IGNORE CHARACTER
	SUBI	T1," "			;CONVERT ASCII TO SIXBIT
	IDPB	T1,T2			;SAVE THE CHARACTER
	JRST	SIXI.1			;GET ANOTHER ONE

SIXI.5:	MOVE	T2,T1			;GET TERMINATING CHARACTER
	MOVE	T1,T3			;GET RESULT
	POP	P,(P)			;TRIM STACK
	POPJ	P,			;RETURN


; Output a sixbit word
; Call:	MOVE	T1, word
;	PUSHJ	P,SIXOUT
;	<RETURN>
;
SIXOUT:	SKIPN	T2,T1			;COPY WORD TO OUTPUT
	POPJ	P,			;NOTHING TO DO

SIXO.1:	LSHC	T1,6			;SHIFT IN A CHARACTER
	ANDI	T1,77			;NO JUNK
	ADDI	T1," "			;CONVERT TO ASCII
	PUSHJ	P,TYO			;OUTPUT IT
	JUMPN	T2,SIXO.1		;LOOP
	POPJ	P,			;RETURN
SUBTTL	Text I/O -- Octal


; Input an octal word
; Call:	PUSHJ	P,OCTIN
;	<RETURN>			;T1:= WORD, T2:= TERMINATING CHARACTER
;
OCTIN:	SETZ	T2,			;CLEAR RESULT AND MASK
	PUSHJ	P,FLUSH			;EAT LEADING SPACES AND TABS
	CAIL	T1,"A"			;CHECK FOR
	CAILE	T1,"Z"			; A LETTER
	JRST	OCTI.2			;ASSUME A DIGIT
	PUSHJ	P,BACKUP		;BACKUP THE BYTE POINTER
	JRST	SIXIN			;GO INPUT SIXBIT

OCTI.1:	PUSHJ	P,TYI			;GET A CHARACTER

OCTI.2:	CAIL	T1,"0"			;RANGE CHECK
	CAILE	T1,"7"			; FOR AN OCTAL DIGIT
	JRST	OCTI.3			;NO GOOD - FINISH UP
	LSH	T2,3			;SHIFT RESULT
	SUBI	T1,"0"			;CONVERT ASCII TO OCTAL
	IOR	T2,T1			;INCLUDE THE DIGIT
	JRST	OCTI.1			;LOOP

OCTI.3:	EXCH	T1,T2			;SWAP RESULT AND TERMINATING CHARACTER
	POPJ	P,			;RETURN


; Output an octal word
; Call:	MOVE	T1, word
;	PUSHJ	P,OCTOUT
;
OCTOUT:	SKIPL	T1			;NEGATIVE?
	JRST	OCTO.1			;NO
	PUSH	P,T1			;SAVE NUMBER
	MOVEI	T1,"-"			;GET MINUS SIGN
	PUSHJ	P,TYO			;OUTPUT IT
	POP	P,T1			;GET NUMBER
	MOVMS	T1			;MAKE IT POSITIVE

OCTO.1:	IDIVI	T1,10			;DIVIDE BY RADIX
	PUSH	P,T2			;SAVE REMAINDER
	SKIPE	T1			;DONE?
	PUSHJ	P,OCTO.1		;RECURSE
	POP	P,T1			;GET A DIGIT
	ADDI	T1,"0"			;CONVERT TO ASCII
	JRST	TYO			;OUTPUT CHARACTER AND RETURN


; Output a CRLF
; Call:	PUSHJ	P,TCRLF
;
TCRLF:	MOVEI	T1,15			;GET A <CR>
	PUSHJ	P,TYO			;TYPE IT
	MOVEI	T1,12			;GET A <LF>
	JRST	TYO			;TYPE IT AND RETURN


; Output a PC
; Call:	MOVE	T1, PC
;	PUSHJ	P,PCOUT
;
PCOUT:	TLNN	T1,-1			;A SECTION NUMBER?
	JRST	PCOU.1			;NO
	PUSH	P,T1			;SAVE PC
	HLRZS	T1			;GET SECTION
	PUSHJ	P,OCTOUT		;TYPE IT
	MOVEI	T1,","			;GET SEPARATOR
	PUSHJ	P,TYO			;TYPE IT
	PUSHJ	P,TYO			;AGAIN
	POP	P,T1			;RESTORE PC
	HRRZS	T1			;GET RELATIVE PC

PCOU.1:	HRLO	T2,T1			;MAKE IT PC,,-1

PCOU.2:	LSHC	T1,3			;SHIFT IN A DIGIT
	ANDI	T1,7			;STRIP OFF JUNK
	ADDI	T1,"0"			;MAKE IT ASCII
	PUSHJ	P,TYO			;TYPE IT
	TRNE	T2,-1			;DONE SIX DIGITS YET?
	JRST	PCOU.2			;NO--LOOP
	POPJ	P,			;RETURN
SUBTTL	Text I/O -- Filespec


; Output a filespec
; Call:	PUSHJ	P,FILOUT
;	<RETURN>
;
FILOUT:	MOVE	T1,FOPBLK+.FODEV	;GET DEVICE
	PUSHJ	P,SIXOUT		;OUTPUT IT
	MOVEI	T1,":"			;GET SEPARATOR
	PUSHJ	P,TYO			;TYPE COLON
	MOVE	T1,LERBLK+.RBNAM	;GET NAME
	PUSHJ	P,SIXOUT		;OUTPUT IT
	MOVEI	T1,"."			;GET SEPARATOR
	PUSHJ	P,TYO			;OUTPUT PERIOD
	HLLZ	T1,LERBLK+.RBEXT	;GET EXTENSION
	PUSHJ	P,SIXOUT		;OUTPUT IT
	MOVEI	T1,"["			;GET PATH DELIMITER
	PUSHJ	P,TYO			;OUTPUT
	SKIPGE	T1,PTHBLK+.PTPPN	;GET PPN
	JRST	FILO.1			;IT'S SIXBIT
	HLRZS	T1			;GET PROJECT NUMBER
	PUSHJ	P,OCTOUT		;OUTPUT IT
	MOVEI	T1,","			;GET SEPARATOR
	PUSHJ	P,TYO			;OUTPUT IT
	HRRZ	T1,PTHBLK+.PTPPN	;GET PROGRAMMER NUMBER
	PUSHJ	P,OCTOUT		;OUTPUT
	JRST	FILO.2			;ONWARD

FILO.1:	PUSHJ	P,SIXOUT		;OUTPUT IT

FILO.2:	MOVEI	T3,PTHBLK+.PTSFD	;POINT TO START OF SFDS

FILO.3:	SKIPN	(T3)			;HAVE AN SFD
	JRST	FILO.4			;END OF PATH
	MOVEI	T1,","			;GET SEPARATOR
	PUSHJ	P,TYO			;OUTPUT IT
	MOVE	T1,(T3)			;GET AN SFD
	PUSHJ	P,SIXOUT		;OUTPUT IT
	AOJA	T3,FILO.3		;LOOP

FILO.4:	MOVEI	T1,"]"			;GET END OF PATH
	JRST	TYO			;OUTPUT IT AND RETURN
SUBTTL	Text I/O -- Miscellaneous


; Set up byte pointer and count
; Call:	MOVE	T1, address to store text or 0 for TTY output
;	MOVE	T2, character count
;	PUSHJ	P,TXTSET
;
TXTSET:	SKIPE	T1			;OUTPUT TO TTY?
	HRLI	T1,(POINT 7,)		;NO--MAKE A BYTE POINTER
	MOVEM	T1,BYTPTR		;SAVE IT
	MOVEM	T2,BYTCNT		;SAVE CHARACTER COUNT
	POPJ	P,			;RETURN


; Flush leading spaces and tabs
; Call:	PUSHJ	P,FLUSH
;	<RETURN>			;T1:= FIRST NON-BLANK CHARACTER
;
FLUSH:	PUSHJ	P,TYI			;GET A CHARACTER
	CAIN	T1," "			;A SPACE?
	JRST	FLUSH			;YES - EAT IT
	POPJ	P,			;RETURN


; Back up the text byte pointer 1 character
; Call:	PUSHJ	P,BACKUP
;
; On return, T1 has been updated with the current character
;
BACKUP:	MOVE	T1,BYTPTR		;GET THE BYTE POINTER
	ADD	T1,[70000,,0]		;BACKUP 1 CHARACTER
	SKIPG	T1			;OVER A WORD BOUNDRY?
	SUB	T1,[430000,,1]		;YES - BACKUP A WORD
	MOVEM	T1,BYTPTR		;SAVE UPDATED POINTER
	LDB	T1,BYTPTR		;LOAD THE PREVIOUS CHARACTER
	POPJ	P,			;RETURN
SUBTTL	Paging -- Check accessibility


; Check accessibility of a page in our address space
; Call:	MOVE	T1, page number
;	PUSHJ	P,PAGACC
;	<NON-SKIP>		;PAGE DOES NOT EXIST
;	<SKIP>			;PAGE EXISTS
;
PAGACC:	MOVEM	T1,UUOARG		;SAVE PAGE NUMBER
	HRLI	T1,.PAGCA		;LOAD A FUNCTION CODE
	PAGE.	T1,			;READ ACCESS BITS
	  SETO	T1,			;ASSUME PAGE NOT THERE
	TLNN	T1,(PA.GNE)		;NON-EXISTANT PAGE?
	AOS	(P)			;NO
	MOVE	T1,UUOARG		;RELOAD PAGE NUMBER
	POPJ	P,			;RETURN


; Check to see if the a reference to a page will cause
; an illegal memory reference.  If so, create it.
; Call:	MOVE	T1, page number
;	PUSHJ	P,PAGCHK
;	<NON-SKIP>			;PAGE CREATE FAILED
;	<SKIP>				;PAGE EXISTS
;
PAGCHK:	PUSHJ	P,PAGACC		;CHECK ACCESSIBILITY
	  JRST	PAGCRE			;CREATE IT AND RETURN
	JRST	CPOPJ1			;IT ALREADY EXISTS
SUBTTL	Paging -- Create/Destroy


; Create or destroy a page in our address space
; Call:	MOVE	T1, page number
;	PUSHJ	P,PAGCRE/PAGDES
;	<NON-SKIP>			;FAILED
;	<SKIP>				;SUCEEDED
;
PAGDES:	TLO	T1,(PA.GAF)		;LITE THE DESTROY BIT
PAGCRE:	MOVEM	T1,UUOARG+1		;SAVE IT
	MOVEI	T1,1			;ONE WORD
	MOVEM	T1,UUOARG+0		;SAVE WORD COUNT
	MOVE	T1,[.PAGCD,,UUOARG]	;SET UP UUO
	PAGE.	T1,			;CREATE OR DESTROY A PAGE
	  ERR.	(,.+2)			;CAN'T
	AOS	(P)			;FORCE SKIP RETURN
	MOVE	T1,UUOARG+1		;RELOAD THE PAGE NUMBER
	TLZ	T1,(PA.GAF)		;TURN OFF THE ALTERNATE FUNCTION BIT
	POPJ	P,			;RETURN
SUBTTL	Paging -- SPY page creation


; Create a SPY page using physical or virtual mapping
; Call:	MOVE	T1, monitor page
;	MOVE	T2, user page
;	PUSHJ	P,PAGSPY
;	<NON-SKIP>			;FAILED
;	<SKIP>				;SUCEEDED
;
PAGSPY:	HRLZM	T1,UUOARG+1		;SAVE MONITOR PAGE NUMBER
	HRRM	T2,UUOARG+1		;SAVE USER PAGE NUMBER
	MOVEI	T1,1			;ONE WORD
	MOVEM	T1,UUOARG+0		;SAVE WORD COUNT
	MOVE	T1,[.PAGSP,,UUOARG]	;SET UP UUO
	TLNN	F,FL.PPM!FL.TPP		;PHYSICAL PAGE MAPPING?
	TDZA	T2,T2			;NO
	MOVEI	T2,UU.PHY		;YES
	PAGE.	T1,(T2)			;CREATE A SPY PAGE
	  ERR.	(,.+2)			;CAN'T
	AOS	(P)			;FORCE SKIP RETURN
	TLZ	F,FL.TPP		;CLEAR TEMPORARY PHYSICAL PAGE MAPPING
	HLRZ	T1,UUOARG+1		;RELOAD MONITOR PAGE NUMBER
	HRRZ	T2,UUOARG+2		;RELOAD USER PAGE NUMBER
	POPJ	P,			;RETURN
SUBTTL	File I/O -- Open a file


; Open a file pointer to by the calling program
; Call:	MOVE	T1, address of ASCIZ filespec
;	PUSHJ	P,FILOPN
;
FILOPN:	PUSHJ	P,SCAN			;SCAN FILESPEC AND LOAD UUO BLOCKS
	  POPJ	P,			;CAN'T
	TLNE	F,FL.SIO		;SUPER I/O?
	TLNN	F,FL.EXE		;AND .EXE FILE?
	  SKIPA				;OK
	ERR.	(CMF,CPOPJ)		;CONFLICTING MAPPING CODE AND FLAGS
	MOVEI	T1,.FORED		;ASSUME ONLY READING
	TLNE	F,FL.PAT		;PATCHING?
	MOVEI	T1,.FOSAU		;YES - USE UPDATE MODE
	TLNE	F,FL.SIO		;SUPER I/O?
	MOVEI	T1,.FOSIO		;YES - USE SUPER I/O MODE
	TLO	T1,(FO.ASC)		;ASSIGN A CHANNEL
	MOVEM	T1,FOPBLK+.FOFNC	;SAVE FUNCTION WORD
	MOVEI	T1,.IODMP		;DUMP MODE
	TLNE	F,FL.PIO		;PHYSICAL ONLY LOOKUP/ENTER?
	TLO	T1,(UU.PHS)		;YES
	MOVEM	T1,FOPBLK+.FOIOS	;SAVE IT
	MOVEI	T1,LERBLK		;GET LOOKUP/ENTER BLOCK ADDRESS
	MOVEM	T1,FOPBLK+.FOLEB	;SAVE IT
	MOVEI	T1,LERSIZ		;GET SIZE OF LOOKUP/ENTER BLOCK
	MOVEM	T1,LERBLK+.RBCNT	;SAVE IT
	MOVE	T1,[PTHSIZ,,PTHBLK]	;GET PATH BLOCK ADDRESS
	MOVEM	T1,FOPBLK+.FOPAT	;SAVE FOR READING PATH BACK
	SKIPE	PTHBLK+.PTPPN		;HAVE A DIRECTORY?
	HRRZM	T1,LERBLK+.RBPPN	;YES--SAVE FOR LOOKUP/ENTER
	MOVE	T1,[FILSIZ,,FILBLK]	;POINT TO THE BLOCK
	MOVEM	T1,FOPBLK+.FOFSP	;SAVE RETURNED FILESPEC POINTER
	MOVE	T1,[FOPSIZ,,FOPBLK]	;SET UP UUO
	FILOP.	T1,			;OPEN THE FILE
	  ERR.	(,CPOPJ)		;FILOP. UUO FAILURE
	MOVE	T1,FOPBLK+.FOFNC	;GET FUNCTION CODE WORD
	AND	T1,[FO.CHN]		;KEEP JUST THE CHANNEL NUMBER
	MOVEM	T1,FILCHN		;SAVE IT
	PUSHJ	P,FILXTR		;EXTRACT THE FULL FILESPEC
	JRST	CPOPJ1			;RETURN
; Here to extract the actual filespec and return it
; to the caller.
;
FILXTR:	MOVE	T1,PTHBLK+.PTSTR	;GET DEVICE NAME
	MOVEM	T1,FOPBLK+.FODEV	;SET IT JUST INCASE PATH. UUO FAILS
	MOVEI	T1,FILTAB		;POINT TO TABLE
	SKIPE	FILBLK+.FOFDV		;HAVE A RETURNED FILESPEC?

FILX.1:	SKIPN	(T1)			;END OF TABLE?
	JRST	FILX.2			;YES
	HLRZ	T2,(T1)			;GET SOURCE ADDRESS
	HRRZ	T3,(T1)			;GET DESTINATION ADDRESS
	SKIPE	T4,(T2)			;GET A WORD
	MOVEM	T4,(T3)			;PUT A WORD
	AOJA	T1,FILX.1		;LOOP

FILX.2:	SETZM	MAPDAT+.MPAFS		;CLEAR FIRST WORD
	MOVE	T1,[MAPDAT+.MPAFS,,MAPDAT+.MPAFS+1] ;SET UP BLT
	BLT	T1,MAPDAT+.MPAFS+.MPFWD	;CLEAR BLOCK
	MOVEI	T1,MAPDAT+.MPAFS	;POINT TO ACTUAL FILESPEC STORAGE
	MOVEI	T2,<.MPFWD*5>-1		;GET MAXIMUM BYTE COUNT
	PUSHJ	P,TXTSET		;SETUP BYTE POINTER AND COUNT
	PUSHJ	P,FILOUT		;OUTPUT FILESPEC
	POPJ	P,			;RETURN


; Translation table
;
FILTAB:	FILBLK+.FOFDV,,FOPBLK+.FODEV	;DEVICE
	FILBLK+.FOFFN,,LERBLK+.RBNAM	;FILE NAME
	FILBLK+.FOFEX,,LERBLK+.RBEXT	;EXTENSION
	FILBLK+.FOFPP,,PTHBLK+.PTPPN	;PPN
	FILBLK+.FOFSF+0,,PTHBLK+.PTSFD+0;SFD #1
	FILBLK+.FOFSF+1,,PTHBLK+.PTSFD+1;SFD #2
	FILBLK+.FOFSF+2,,PTHBLK+.PTSFD+2;SFD #3
	FILBLK+.FOFSF+3,,PTHBLK+.PTSFD+3;SFD #4
	FILBLK+.FOFSF+4,,PTHBLK+.PTSFD+4;SFD #5
	EXP	0			;TERMINATE TABLE
SUBTTL	File I/O -- Close a file


; Close a file
; Call:	PUSHJ	P,FILCLS
;
FILCLS:	SKIPN	T1,FILCHN		;WE ONLY USE EXTENDED CHANNELS
	POPJ	P,			;DON'T ZAP CHANNEL ZERO
	IORI	T1,.FOREL		;INCLUDE THE FUNCTION CODE
	MOVEM	T1,FOPBLK+.FOFNC	;SAVE IT
	MOVE	T1,[1,,FOPBLK]		;SET UP UUO
	FILOP.	T1,			;CLOSE THE FILE
	  JFCL				;IGNORE ERRORS
	SETZM	FILCHN			;SO WE DON'T TRY THIS AGAIN
	POPJ	P,			;RETURN
SUBTTL	File I/O -- Position a file


; Position file for input or output
; Call:	MOVE	T1, block number
;	PUSHJ	P,FILIPS		;INPUT
;	PUSHJ	P,FILOPS		;OUTPUT
;
FILIPS:	MOVEM	T1,FOPBLK+.FOIOS	;SAVE BLOCK NUMBER
	MOVEI	T1,.FOUSI		;USETI FUNCTION
	JRST	FILPOS			;CONTINUE
FILOPS:	MOVEM	T1,FOPBLK+.FOIOS	;SAVE BLOCK NUMBER
	MOVEI	T1,.FOUSO		;USETO FUNCTION
FILPOS:	IOR	T1,FILCHN		;INCLUDE THE CHANNEL NUMBER
	MOVEM	T1,FOPBLK+.FOFNC	;SAVE FUNCTION WORD
	MOVE	T1,[2,,FOPBLK]		;SET UP UUO
	FILOP.	T1,			;POSITION FOR INPUT OR OUTPUT
	  POPJ	P,			;CAN'T
	JRST	CPOPJ1			;RETURN
SUBTTL	File I/O -- Input/Output


FILRED:	SKIPA	T1,[.FOINP]		;INPUT FUNCTION
FILWRT:	MOVEI	T1,.FOOUT		;OUTPUT FUNCTION
	SETZM	IOLIST+1		;TERMINATE LIST
	IOR	T1,FILCHN		;INCLUDE THE CHANNEL NUMBER
	MOVEM	T1,FOPBLK+.FOFNC	;SAVE FUNCTION WORD
	MOVEI	T1,IOLIST		;POINT TO THE I/O COMMAND LIST
	MOVEM	T1,FOPBLK+.FOIOS	;TELL THE MONITOR
	MOVE	T1,[2,,FOPBLK]		;SET UP UUO
	FILOP.	T1,			;READ OR WRITE THE FILE
	  POPJ	P,			;CAN'T
	JRST	CPOPJ1			;RETURN
SUBTTL	File I/O -- Scan a filespec


; This routine will scan off a filespec and load the appropriate
; locations in the FILOP., LOOKUP/ENTER and PATH. UUO blocks
; Call:	MOVE	T1, address of ASCIZ filespec
;	PUSHJ	P,SCAN
;
SCAN:	HRLOI	T2,377777		;A LARGE NUMBER
	PUSHJ	P,TXTSET		;SET UP FOR TEXT I/O
	SETZM	FOPBLK			;CLEAR THE FIRST WORD
	MOVE	T1,[FOPBLK,,FOPBLK+1]	;SET UP BLT
	BLT	T1,FOPBLK+FOPSIZ-1	;CLEAR THE FILOP. UUO BLOCK
	SETZM	LERBLK			;CLEAR THE FIRST WORD
	MOVE	T1,[LERBLK,,LERBLK+1]	;SET UP BLT
	BLT	T1,LERBLK+LERSIZ-1	;CLEAR THE LOOKUP/ENTER UUO BLOCK
	SETZM	PTHBLK			;CLEAR THE FIRST WORD
	MOVE	T1,[PTHBLK,,PTHBLK+1]	;SET UP BLT
	BLT	T1,PTHBLK+PTHSIZ-1	;CLEAR THE PATH. UUO BLOCK
	GETPPN	T1,			;GET OUR PPN
	  JFCL				;INCASE OF JACCT
	MOVEM	T1,FILPPN		;SAVE IT
	TLZ	F,FL.DEV!FL.NAM!FL.EXT!FL.DIR ;CLEAR SCANNER FLAGS
SCAN.1:	PUSHJ	P,SIXIN			;GET A FILESPEC PART
	JUMPN	T1,SCAN.4		;SEE WHAT WE GOT

SCAN.2:	CAIN	T2,"."			;AN EXTENSION?
	JRST	SCAN.5			;YES
	CAIE	T2,"["			;A PATH?
	CAIN	T2,"<"			;2741 STYLE?
	JRST	SCAN.6			;YES TO EITHER
	CAIN	T2," "			;SPACE?
	JRST	SCAN.1			;KEEP SCANNING
	PUSHJ	P,BACKUP		;BACKUP TO THE TERMINATING CHARACTER
	JRST	SCNDEF			;CHECK LEGALITY AND DO DEFAULTING

; Device
;
SCAN.3:	TLOE	F,FL.DEV		;ALREADY HAVE A DEVICE?
	ERR.	(DDI,CPOPJ)		;DOUBLE DEVICE ILLEGAL
	MOVEM	T1,FOPBLK+.FODEV	;SAVE DEVICE
	JRST	SCAN.1			;KEEP SCANNING

; File name
;
SCAN.4:	CAIN	T2,":"			;A DEVICE?
	JRST	SCAN.3			;YES
	TLOE	F,FL.NAM		;ALREADY HAVE A FILE NAME?
	ERR.	(DFI,CPOPJ)		;DOUBLE FILE NAME ILLEGAL
	MOVEM	T1,LERBLK+.RBNAM	;SAVE FILE NAME
	JRST	SCAN.2			;GO EXAMINE TERMINATOR

; Extension
;
SCAN.5:	TLOE	F,FL.EXT		;ALREADY HAVE AN EXTENSION
	ERR.	(DEI,CPOPJ)		;DOUBLE EXTENSION ILLEGAL
	PUSHJ	P,SIXIN			;GET A WORD
	HLLZM	T1,LERBLK+.RBEXT	;SAVE EXTENSION
	JRST	SCAN.2			;GO EXAMINE TERMINATOR

; Path
;
SCAN.6:	TLOE	F,FL.DIR		;ALREADY HAVE A DIRECTORY?
	ERR.	(DPI,CPOPJ)		;DOUBLE PATH ILLEGAL
	PUSHJ	P,SCNPTH		;SCAN A PATH
	  POPJ	P,			;FAILED
	CAIE	T2,"]"			;END OF PATH?
	CAIN	T2,">"			;2741 STYLE?
	JRST	SCAN.1			;YES - LOOP BACK FOR MORE
	JRST	SCAN.2			;NO - CHECK OTHER TERMINATORS
; Scan a path
;
SCNPTH:	PUSHJ	P,FLUSH			;EAT LEADING SPACES AND TABS
	CAIN	T1,"-"			;WANT DEFAULT PATH?
	JRST	SCNP.4			;YES
	PUSHJ	P,BACKUP		;BACKUP THE BYTE POINTER
	PUSHJ	P,OCTIN			;GET PROJECT NUMBER
	TLNN	T1,777777		;SIXBIT PPN?
	HRLZS	T1			;NO
	TLNN	T1,777777		;HAVE A PROJECT NUMBER?
	HLL	T1,FILPPN		;NO
	IORM	T1,PTHBLK+.PTPPN	;SAVE IT
	TRNE	T1,777777		;SIXBIT PPN?
	JRST	SCNP.1			;YES
	CAIE	T2,","			;MUST HAVE A COMMA HERE
	ERR.	(PSE,CPOPJ)		;PATH SYNTAX ERROR
	PUSHJ	P,OCTIN			;GET PROGRAMMER NUMBER
	TLNE	T1,777777		;SIXBIT PPN?
	HLRZS	T1			;YES--TRUNCATE TO 18 BITS
	TRNN	T1,777777		;HAVE A PROGRAMMER NUMBER?
	HRR	T1,FILPPN		;NO
	IORM	T1,PTHBLK+.PTPPN	;SAVE IT

SCNP.1:	MOVEI	T4,PTHBLK+.PTSFD	;POINT TO START OF SFDS
	HRLI	T4,-<PTHSIZ-.PTSFD-1>	;MAKE AN AOBJN POINTER

SCNP.2:	CAIE	T2,","			;LEGAL SEPARATOR?
	JRST	CPOPJ1			;NO--DONE
	PUSHJ	P,SIXIN			;GET AN SFD
	JUMPE	T1,[ERR. (NSI,CPOPJ)]	;NULL SFDS ARE ILLEGAL
	MOVEM	T1,0(T4)		;SAVE IT
	AOBJN	T4,SCNP.2		;LOOP
	ERR.	(SND,CPOPJ)		;SFDS NESTED TOO DEEP

SCNP.4:	SETOM	PTHBLK+.PTFCN		;SET FUNCTION CODE
	MOVE	T1,[PTHSIZ,,PTHBLK]	;SET UP UUO
	PATH.	T1,			;READ OUR DEFAULT PATH
	  ERR.	(CRP,CPOPJ)		;UUO FAILED--CAN'T READ PATH
	PUSHJ	P,FLUSH			;EAT SPACES AND TABS
	JRST	CPOPJ1			;AND RETURN


; Check for a legal filespec and do extension defaulting
;
SCNDEF:	MOVSI	T1,'DSK'		;GET A DEVICE
	TLNN	F,FL.DEV		;ONE SPECIFIED?
	MOVEM	T1,FOPBLK+.FODEV	;DEFAULT TO DSK
	TLNN	F,FL.NAM!FL.EXT!FL.DIR	;ANY FILESPEC PARTS?
	JRST	CPOPJ1			;NO
	TLNN	F,FL.EXE		;.EXE FILE?
	JRST	CPOPJ1			;A DATA FILE
	MOVSI	T1,'EXE'		;GET AN EXTENSION
	TLNN	F,FL.EXT		;EXTENSION SPECIFIED?
	MOVEM	T1,LERBLK+.RBEXT	;DEFAULT IT
	JRST	CPOPJ1			;RETURN
SUBTTL	EXE file routines -- Load and validate directory


; Read an .EXE file directory into core
; Call:	PUSHJ	P,EXEDIR
;	<NON-SKIP>			;BAD DIRECTORY OR I/O ERROR
;	<SKIP>				;DIRECTORY IN CORE
;
EXEDIR:	MOVEI	T1,1			;GET STARTING BLOCK NUMBER OF DIRECTORY
	PUSHJ	P,FILIPS		;POSITION FOR INPUT
	  POPJ	P,			;CAN'T
	MOVE	T2,CSHPAG		;GET STARTING PAGE NUMBER IN CACHE
	LSH	T2,11			;CONVERT TO AN ADDRESS
	MOVEM	T2,DIRADR		;SAVE IT
	MOVE	T3,T2			;COPY IT
	SETZM	DIRPGS			;CLEAR COUNT OF DIRECTORY PAGES

EXED.1:	MOVE	T1,DIRADR		;GET DIRECTORY BASE ADDRESS
	MOVE	T4,DIRPGS		;GET EXISTING COUNT OF DIRECTORY PAGES
	CAIL	T4,PAGCNT		;ENOUGH FREE PAGES LEFT FOR MAPPING?
	ERR.	(NRE,CPOPJ)		;NO ROOM TO CACHE .EXE FILE DIRECTORY
	LSH	T4,-11			;CONVERT TO ADDRESS OFFSET
	ADDI	T1,-1(T4)		;GET ADDRESS OF AVAILABLE BUFFER
	HRLI	T1,-PAGSIZ		;MAKE AN IOWD
	MOVEM	T1,IOLIST		;SAVE IT
	MOVEI	T1,1(T1)		;GET ADDRESS ON NEW PAGE
	LSH	T1,-11			;CONVERT TO A PAGE NUMBER
	PUSHJ	P,PAGCHK		;MAKE SURE THE PAGE IS THERE
	  POPJ	P,			;CAN'T CREATE IT
	PUSHJ	P,FILRED		;READ A PAGE
	  ERR.	(EIE,CPOPJ)		;.EXE FILE DIRECTORY INPUT ERROR
	AOS	DIRPGS			;COUNT DIRECTORY PAGES READ INTO CORE
	TRZ	T3,PAGSIZ-1		;STRIP OFF INDEX INDEX INTO PAGE
	ADDI	T3,PAGSIZ		;ROUND UP A PAGE

EXED.2:	SKIPE	T1,(T2)			;END OF DIRECTORY?
	JRST	EXED.3			;NO
	MOVN	T1,DIRPGS		;GET -NUMBER OF DIRECTORY PAGES
	ADDM	T1,PAGCNT		;ADJUST COUNT OF FREE PAGES
	MOVNS	T1			;GET +NUMBER OF DIRECTORY PAGES
	ADDM	T1,CSHPAG		;UPDATE FIRST FREE PAGE FOR CACHING
	JRST	CPOPJ1			;AND RETURN
EXED.3:	HLRZS	T1			;KEEP JUST THE BLOCK TYPE
	MOVE	T4,[-EXELEN,,EXETAB]	;AOBJN POINTER TO EXE BLOCK TYPES
	CAME	T1,(T4)			;A MATCH?
	AOBJN	T4,.-1			;LOOP
	JUMPGE	T4,[ERR. (BED,CPOPJ)]	;BAD EXE FILE DIRECTORY
	HRRZ	T1,(T2)			;GET OFFSET TO NEXT BLOCK
	ADD	T2,T1			;POINT TO IT
	CAMGE	T2,T3			;NEED ANOTHER DIRECTORY PAGE?
	JRST	EXED.2			;CHECK OUT ALL BLOCKS
	JRST	EXED.1			;GO READ ANOTHER PAGE INTO CORE
SUBTTL	EXE file routines -- Find a file page


; Search a directory for a page
; Call:	MOVE	T1, page number
;	PUSHJ	P,EXEPAG
;	<NON-SKIP>			;PAGE NOT FOUND, I/O ERROR
;	<SKIP>				;PAGE FOUND, T1:= FILE PAGE NUMBER
;
EXEPAG:	TLNN	F,FL.EXE		;MAPPING AN .EXE FILE?
	JRST	CPOPJ1			;NO - THEN ITS A DATA FILE
	MOVE	T4,T1			;SAVE PAGE NUMBER
	MOVEI	T1,.SVDIR		;GET DESIRED BLOCK TYPE
	PUSHJ	P,EXEBLK		;SEARCH FOR IT
	  ERR.	(BED,CPOPJ)		;BAD EXE FILE DIRECTORY
	MOVE	T1,T4			;GET PAGE NUMBER BACK AGAIN
	ADDI	T2,1			;POINT TO NEXT WORD

EXEP.1:	HLRZ	T3,.SVFPF(T2)		;GET POSSIBLE BLOCK TYPE
	CAIN	T3,.SVEND		;END OF DIRECTORY?
	  ERR.	(NXA,CPOPJ)		;NON-EXISTANT ADDRESS IN FILE
	LDB	T3,EXEREP		;GET REPEAT COUNT
	LDB	T4,EXEPPN		;GET PROCESS PAGE NUMBER
	ADD	T4,T3			;GET ENDING PAGE NUMBER
	CAMGE	T4,T1			;HIGH PAGE LESS THAN TARGET PAGE?
	JRST	EXEP.3			;YES

EXEP.2:	CAMN	T4,T1			;FOUND THE PAGE WE WANT?
	JRST	EXEP.4			;YES
	SUBI	T4,1			;DECREMENT PAGE NUMBER
	SOJGE	T3,EXEP.2		;LOOP

EXEP.3:	ADDI	T2,2			;POINT TO NEXT DIRECTORY PAGE ENTRY
	JRST	EXEP.1			;TRY AGAIN

EXEP.4:	LDB	T1,EXEFPN		;GET FILE PAGE NUMBER
	ADD	T1,T3			;ADD REPEAT COUNT
	JRST	CPOPJ1			;AND RETURN


; Byte pointers to directory entry parts
;
EXEREP:	POINTR	(.SVPPC(T2),SV%REP)	;REPEAT COUNT
EXEPPN:	POINTR	(.SVPPC(T2),SV%PPN)	;PROCESS PAGE NUMBER
EXEFPN:	POINTR	(.SVFPF(T2),SV%FPN)	;FILE PAGE NUMBER
SUBTTL	EXE file routines -- Find a directory block


; Find a block in an .EXE directory
; Call:	MOVE	T1, block type
;	PUSHJ	P,EXEBLK
;	<NON-SKIP>		;CAN'T FIND IT
;	<SKIP>			;BLOCK FOUND
;
; On sucessful return, T1:= block type,,length and T2:= directory address
;
EXEBLK:	MOVE	T2,[-EXELEN,,EXETAB]	;AOBJN POINTER TO EXE BLOCK TYPES
	CAME	T1,(T2)			;A MATCH?
	AOBJN	T2,.-1			;LOOP
	JUMPGE	T2,[ERR. (BED,CPOPJ)]	;BAD EXE FILE DIRECTORY
	MOVE	T2,DIRADR		;GET STARTING ADDRESS OF DIRECTORY

EXEB.1:	SKIPN	T3,(T2)			;END OF DIRECTORY?
	ERR.	(BED,CPOPJ)		;BAD EXE FILE DIRECTORY
	HLRZS	T3			;PUT IN RH
	CAMN	T3,T1			;A MATCH?
	JRST	EXEB.2			;YES
	HRRZ	T3,(T2)			;GET LENGTH
	ADD	T2,T3			;POINT TO NEXT BLOCK
	JRST	EXEB.1			;LOOP

EXEB.2:	MOVE	T1,(T2)			;GET BLOCK TYPE,,LENGTH
	JRST	CPOPJ1			;AND RETURN


; Table of legal .EXE file directory block types
;
EXETAB:	EXP	.SVDIR			;START OF FILE TO CORE MAP
	EXP	.SVEND			;END OF EXE FILE DIRECTORY
;	EXP	.SVEVC			;ENTRY VECTOR
EXELEN==.-EXETAB			;LENGTH OF TABLE
SUBTTL	FORTRAN interface


MAPD::	MOVEI	.AP,@0(16)		;GET ARGUMENT POINTER
	PUSHJ	P,.MAPD			;DO A DEPOSIT
	 JRST	MAPFER			;ERROR
	POPJ	P,			;AND RETURN

MAPE::	MOVE	.AP,@0(16)		;GET ARG
	PUSHJ	P,.MAPE			;EXAMINE
	 JRST	MAPFER			;ERROR
	MOVE	0,.AP			;INTO 0 FOR FORTRAN FUNCTION
	POPJ	P,			;AND RETURN

MAPG::	MOVE	.AP,@0(16)		;GET ARG
	PUSHJ	P,.MAPG			;GETTAB SIMULATION
	 JRST	MAPFER
	MOVE	0,.AP			;INTO 0 FOR FORTRAN FUNCTION
	POPJ	P,			;AND RETURN

MAPI::	MOVEI	.AP,@0(16)		;ADDRESS OF ARG BLOCK
	PUSHJ	P,.MAPI			;INITIALIZE
	 JRST	MAPFER			;ERROR
	POPJ	P,			;AND RETURN

MAPJ::	MOVEI	.AP,@0(16)		;ADDRESS OF ARG BLOCK
	PUSHJ	P,.MAPJ			;DO A JOBPEK
	 JRST	MAPFER			;ERROR
	POPJ	P,			;AND RETURN


; Here on an error. See if error dispatch provided on call
;
MAPFER:	HLRE	T1,-1(16)		;GET ARG COUNT
	CAMLE	T1,[-2]			;TWO OR MORE?
	 JRST	MAPFE1			;NO
	MOVEI	T1,@1(16)		;YES--GET DISPATCH
	HRRM	T1,(P)			;STUFF ON STACK
	POPJ	P,			;AND DISPATCH

MAPFE1:	OUTSTR	[ASCIZ/?Unhandled MAP error: /]
	OUTSTR	MAPDAT+.MPMET
	OUTSTR	[BYTE(7) 15,12,0]
	OUTSTR	MAPDAT+.MPXET
	EXIT
SUBTTL	Context switch


; Here to save the user's ACs and set up a new stack. This is a
; co-routine that may NOT be called recursively to save 'n' sets
; of ACs. Skip returns are handled.
; Call:	PUSHJ	P,CONTXT
;
CONTXT:	AOSE	CTXFLG			;ALREADY CONTEXT SWITCHED?
	POPJ	P,			;YES - THEN DO NOTHING
	MOVEM	0,USRACS+0		;SAVE AC 0
	MOVE	0,[1,,USRACS+1]		;SET UP BLT
	BLT	0,USRACS+17		;SAVE ACS 1 - 17
	MOVE	P,[IOWD	PDLSIZ,MAPPDL]	;SETUP INTERNAL PDL
	MOVE	F,MAPFLG		;GET MAPPING FLAGS
	TLNE	F,FL.RTM		;WANT TO ACCUMLATE RUNTIME?
	PUSHJ	P,GETRTM		;YES
	SETZM	MAPDAT+.MPECD		;CLEAR OUT ANY OLD ERROR CODE
	SETZM	MAPDAT+.MPMET		;INSURE NO JUNK MAPPING ERROR TEXT
	SETZM	MAPDAT+.MPXET		;INSURE NO JUNK EXTENDED ERROR TEXT
	MOVE	T2,USRACS+P		;GET OLD PDL POINTER
	MOVEI	T2,@0(T2)		;GET CALLER'S ADDRESS
	PUSHJ	P,(T2)			;CALL THE CALLER
	  TDZA	T1,T1			;INDICATE NON-SKIP RETURN
	HRROI	T1,-1			;INDICATE SKIP RETURN
	MOVEM	T1,TFFLAG		;SET TRUE OR FALSE
	TLNE	F,FL.RTM		;WANT TO ACCUMLATE RUNTIME?
	PUSHJ	P,GETRTM		;YES
	MOVEM	F,MAPFLG		;UPDATE MAPPING FLAGS
	MOVE	0,[USRACS+1,,1]		;SET UP BLT
	BLT	0,17			;RESTORE THE ACS
	MOVE	0,USRACS+0		;RELOAD AC 0
	POP	P,(P)			;PRUNE STACK
	SETOM	CTXFLG			;RESET CONTEXT FLAG
	SKIPGE	TFFLAG			;FUNCTION FAIL?
CPOPJ1:	AOS	(P)			;NO - THEN SKIP
CPOPJ:	POPJ	P,			;RETURN


GETRTM:	MOVSI	T2,(RN.PCN)		;RETURN PRECISION RUNTIME
	RUNTIM	T2,			;GET IT
	EXCH	T2,CPUTIM		;SAVE IT AND GET PREVIOUS
	JUMPE	T2,CPOPJ		;RETURN IF CALLED AT CONTEXT ENTRY
	SETZ	T3,			;CLEAR FOR NEXT TIME
	EXCH	T3,CPUTIM		;AND GET OUR RUNTIME NOW
	SUB	T3,T2			;COMPUTE IMCREMENTAL
	ADDM	T3,MAPDAT+.MPRTM	;ACCUMULATE IT
	POPJ	P,			;AND RETURN
SUBTTL	Error handling


ERROR:	DMOVEM	T1,ERRACS+0		;SAVE T1 & T2
	DMOVEM	T3,ERRACS+2		;SAVE T3 & T4

	MOVEI	T1,@(P)			;GET ADDRESS OF ARGUMENTS
	MOVE	T1,(T1)			;GET ERROR CODE,,RETURN ADDRESS
	POP	P,(P)			;TRIM STACK
	SKIPN	MAPDAT+.MPECD		;NESTED ERRORS?
	HLRZM	T1,MAPDAT+.MPECD	;STORE NEW ERROR CODE
	HLL	T1,(P)			;GET PC FLAGS OR SECTION NUMBER
	EXCH	T1,(P)			;SET RETURN PC AND GET PC OF ERROR

	MOVEI	T1,@T1			;EXTRACT JUST THE PC
	SUBI	T1,2			;POINT TO OFFENDING INSTRUCTION
	MOVEM	T1,ERRPC		;SAVE IT
	LDB	T1,[POINT 9,@ERRPC,8]	;GET THE OPCODE
	SKIPE	T1			;OPCODE ZERO IS MEANINGLESS
	CAILE	T1,100			;A UUO?
	SKIPA
	PUSHJ	P,ERRUUO		;GENERATE UUO ERROR TEXT
	PUSHJ	P,ERRMAP		;DO THE MAPPING ERROR

	DMOVE	T1,ERRACS+0		;RESTORE T1 & T2
	DMOVE	T3,ERRACS+2		;RESTORE T3 & T4
	POPJ	P,			;AND RETURN
; Here to type specific mapping errors
;
ERRMAP:	SETZM	MAPDAT+.MPMET		;CLEAR THE FIRST WORD
	MOVE	T1,[MAPDAT+.MPMET,,MAPDAT+.MPMET+1] ;SET UP BLT
	BLT	T1,MAPDAT+.MPMET+.MPEWD-1 ;CLEAR ENTIRE BLOCK
	SKIPN	T3,MAPDAT+.MPECD	;HAVE AN ERROR?
	POPJ	P,			;NO
	HLLZ	T1,MAPERR-1(T3)		;GET PREFIX
	HLRZM	T1,MAPDAT+.MPPFX	;SAVE FOR CALLER
	MOVEI	T1,MAPDAT+.MPMET	;STORE TEXT HERE
	MOVEI	T2,<.MPEWD*5>-1		;MAX NUMBER OF CHARACTERS
	PUSHJ	P,TXTSET		;SET IT UP
	HRRZ	T1,MAPERR-1(T3)		;GET ASSOCIATED ERROR TEXT
	PUSHJ	P,TSTRG			;TYPE IT

ERRM.1:	CAIE	T3,MPGUF%		;GETTAB UUO FAILURE?
	JRST	ERRM.2			;NO
	MOVEI	T1,[ASCIZ |; table = |]	;GET TEXT
	PUSHJ	P,TSTRG			;TYPE IT
	HRRE	T1,USRACS+.AP		;GET TABLE NUMBER
	PUSHJ	P,OCTOUT		;TYPE IT
	MOVEI	T1,[ASCIZ |, index = |]	;GET TEXT
	PUSHJ	P,TSTRG			;TYPE IT
	HLRE	T1,USRACS+.AP		;GET INDEX
	PUSHJ	P,OCTOUT		;TYPE IT
	JRST	ERRM.X			;FINISH UP

ERRM.2:	CAIE	T3,MPDAF%		;DEPOSIT ADDRESS FAILURE?
	CAIN	T3,MPEAF%		;EXAMINE ADDRESS FAILURE?
	SKIPA	T1,USRACS+.AP		;YES--GET ARGUMENT
	JRST	ERRM.3			;NO
	CAIN	T3,MPDAF%		;DEPOSIT?
	MOVE	T1,0(T1)		;GET ADDRESS
	PUSH	P,T1			;SAVE IT
	MOVEI	T1,[ASCIZ |; address = |]	;GET TEXT
	PUSHJ	P,TSTRG			;TYPE IT
	POP	P,T1			;RESTORE ADDRESS
	PUSHJ	P,PCOUT			;TYPE IT
	JRST	ERRM.X			;FINISH UP

ERRM.3:	CAIE	T3,MPMIF%		;MAPPER INITIALIZATION FAILURE
	JRST	ERRM.X			;NO
	HRRZ	T3,F			;GET MAPPING CODE
	CAIE	T3,.MPFIL		;FILE MODE?
	JRST	ERRM.X			;NO
	MOVEI	T1,[ASCIZ |; file = |]	;GET TEXT
	PUSHJ	P,TSTRG			;TYPE IT
	MOVE	T1,USRACS+.AP		;GET ARGUMENT ADDRESS
	MOVE	T1,.MPARG(T1)		;GET ADDRESS OF FILESPEC ADDRESS
	SKIPE	MAPDAT+.MPAFS		;HAVE ACTUAL FILESPEC YET?
	MOVEI	T1,MAPDAT+.MPAFS	;YES--USE THAT
	PUSHJ	P,TSTRG			;TYPE IT
	JRST	ERRM.X			;FINISH UP

ERRM.X:	POPJ	P,			;AND RETURN
; Table of mapping errors
;
	...ERR==0
MAPERR:	MERR.	(BED,<Bad EXE file directory>)
	MERR.	(CMF,<Conflicting mapping code and flags>)
	MERR.	(CRP,<Cannot read default path>)
	MERR.	(DAF,<Deposit address failure>)
	MERR.	(DDI,<Double device illegal>)
	MERR.	(DEI,<Double extension illegal>)
	MERR.	(DFI,<Double file name illegal>)
	MERR.	(DPI,<Double path illegal>)
	MERR.	(DVM,<Deposit value doesn't match existing word>)
	MERR.	(EAF,<Examine address failure>)
	MERR.	(ECS,<Left eye can't SPY>)
	MERR.	(EIE,<EXE file directory input error>)
	MERR.	(GUF,<GETTAB UUO/simulation failure>)
	MERR.	(HAF,<Hash table/chunk allocation failure>)
	MERR.	(IAD,<Illegal address>)
	MERR.	(ICS,<Illegal cache size requested>)
	MERR.	(IJN,<Illegal job number>)
	MERR.	(IMC,<Illegal mapping code>)
	MERR.	(IWE,<Illegal to write Exec Virtual Memory>)
	MERR.	(IWU,<Illegal to write the UPMP>)
	MERR.	(JNA,<Job not addressable>)
	MERR.	(JRW,<JOBPEK UUO failed to read/write another job>)
	MERR.	(JSO,<Job swapped out>)
	MERR.	(MIF,<Mapper initialization failure>)
	MERR.	(NAP,<No access to requested page>)
	MERR.	(NEB,<No EPT for boot CPU>)
	MERR.	(NFC,<No free chunks for cache>)
	MERR.	(NRE,<No room to cache EXE file directory>)
	MERR.	(NSI,<Null SFD illegal>)
	MERR.	(NXA,<Non-existant address in file>)
	MERR.	(PNC,<Page not in core>)
	MERR.	(PSE,<Path syntax error>)
	MERR.	(SIR,<SPT index out of range>)
	MERR.	(SND,<SFDs nested too deep>)
	MERR.	(UPC,<Unimplemented KL paging code>)
; Here to type specific UUO error text
;
ERRUUO:	PUSHJ	P,UUOERR		;TRANSLATE ERROR CODE
	SETZM	MAPDAT+.MPXET		;CLEAR THE FIRST WORD
	MOVE	T1,[MAPDAT+.MPXET,,MAPDAT+.MPXET+1] ;SET UP BLT
	BLT	T1,MAPDAT+.MPXET+.MPEWD-1 ;CLEAR ENTIRE BLOCK
	MOVEI	T1,MAPDAT+.MPXET	;STORE TEXT HERE
	MOVEI	T2,<.MPEWD*5>-1		;MAX NUMBER OF CHARACTERS
	PUSHJ	P,TXTSET		;SET IT UP
	MOVEI	T1,11			;GET A <TAB>
	PUSHJ	P,TYO			;TYPE IT
	MOVE	T1,ERRNAM		;GET UUO NAME
	PUSHJ	P,SIXOUT		;TYPE IT
	MOVEI	T1,[ASCIZ | UUO error |] ;GET TEXT
	PUSHJ	P,TSTRG			;TYPE IT
	LDB	T1,[POINT 4,@ERRPC,12]	;GET UUO AC
	CAIG	T1,T4			;WITHIN THE RANGE
	CAIGE	T1,T1			;OF T1 - T4?
	SKIPA	T1,(T1)			;NO--GET THE ERROR CODE
	MOVE	T1,ERRACS-T1(T1)	;YES--RELOCATE AND GET THE CODE
	PUSHJ	P,OCTOUT		;TYPE IT
	MOVEI	T1,[ASCIZ | at PC |]	;GET TEXT
	PUSHJ	P,TSTRG			;TYPE IT
	MOVE	T1,ERRPC		;GET PC WHERE UUO FAILED
	PUSHJ	P,PCOUT			;TYPE IT
	MOVEI	T1,[ASCIZ |; |]		;GET SEPARATOR
	PUSHJ	P,TSTRG			;TYPE IT
	MOVE	T1,ERRTXT		;GET ADDRESS OF TEXT FOR THIS ERROR
	PUSHJ	P,TSTRG			;TYPE IT
	PUSHJ	P,TCRLF			;TYPE A CRLF
	MOVEI	T1,11			;GET A TAB
	PUSHJ	P,TYO			;TYPE IT
	MOVEI	T1,VERSIO		;POINT TO OUR VERSION
	PUSHJ	P,TSTRG			;TYPE IT
	MOVEI	T1,[ASCIZ | called from PC |]
	PUSHJ	P,TSTRG			;TYPE TEXT
	MOVE	T1,USRACS+P		;GET CALLER'S STACK POINTER
	MOVEI	T1,@-1(T1)		;GET CALLER'S PC +1
	SUBI	T1,1			;ADJUST IT
	PUSHJ	P,PCOUT			;TYPE THE PC
	MOVEI	T1,[ASCIZ |, Mode = |]	;GET TEXT
	PUSHJ	P,TSTRG			;TYPE IT
	MOVE	T1,CODTAB(F)		;GET MAPPING CODE NAME
	PUSHJ	P,TSTRG			;TYPE IT
	MOVEI	T1,[ASCIZ | (physical)|] ;MORE CHATTER
	TLNE	F,FL.PPM		;PHYSICAL PAGE MAPPING?
	PUSHJ	P,TSTRG			;YES
	POPJ	P,			;RETURN
; Translate UUO error code to text
; Note: GETTAB failures are not trapped here
;
UUOERR:	MOVE	T1,[-UUOTSZ,,UUOTAB]	;AOBJN POINTER
	MOVE	T2,@ERRPC		;GET UUO IN QUESTION
	TDZ	T2,[Z 17,@UU.PHY(17)]	;CLEAR OUT JUNK

UUOE.1:	CAMN	T2,0(T1)		;A MATCH?
	JRST	UUOE.2			;YES
	ADD	T1,[2,,2]		;ACCOUNT FOR THREE WORD ENTRIES
	AOBJN	T1,UUOE.1		;TRY THE NEXT ONE
	MOVE	T2,['??????']		;DON'T KNOW THAT ONE
	JRST	UUOE.4			;STRANGE

UUOE.2:	MOVE	T2,1(T1)		;GET UUO NAME
	MOVE	T1,2(T1)		;AOBJN POINTER TO UUO SPECIFIC TABLE
	LDB	T3,[POINT 4,@ERRPC,12]	;GET UUO AC
	CAIG	T3,T4			;WITHIN THE RANGE
	CAIGE	T3,T1			;OF T1 - T4?
	SKIPA	T3,(T3)			;NO--GET THE ERROR CODE
	MOVE	T3,ERRACS-T1(T3)	;YES--RELOCATE AND GET THE CODE

UUOE.3:	HLRZ	T4,(T1)			;GET AN ERROR CODE
	CAMN	T3,T4			;A MATCH?
	JRST	UUOE.5			;YES
	AOBJN	T1,UUOE.3		;LOOP

UUOE.4:	SKIPA	T3,[[ASCIZ |Unknown UUO error code|]]

UUOE.5:	HRRZ	T3,(T1)			;GET ERROR TEXT
	MOVEM	T2,ERRNAM		;SAVE UUO NAME
	MOVEM	T3,ERRTXT		;SAVE ERROR TEXT
	POPJ	P,			;RETURN

UUOTAB:	EXP	<FILOP.>,<SIXBIT /FILOP./>,<-FOPESZ,,FOPERR>
	EXP	<JOBPEK>,<SIXBIT /JOBPEK/>,<-JPKESZ,,JPKERR>
	EXP	<PAGE. >,<SIXBIT /PAGE. />,<-PAGESZ,,PAGERR>
	EXP	<PATH. >,<SIXBIT /PATH. />,<-PATESZ,PATERR>
	EXP	<POKE. >,<SIXBIT /POKE. />,<-POKESZ,,POKERR>
UUOTSZ==.-UUOTAB
; FILOP. UUO errors
;
FOPERR:	ERFNF%,,[ASCIZ |File not found|]
	ERIPP%,,[ASCIZ |Incorrect PPN|]
	ERPRT%,,[ASCIZ |Protection failure|]
	ERFBM%,,[ASCIZ |File being modified|]
	ERDNA%,,[ASCIZ |Device not available|]
	ERNSD%,,[ASCIZ |No such device|]
	ERWLK%,,[ASCIZ |Write-locked|]
	ERSNF%,,[ASCIZ |SFD not found|]
	ERSLE%,,[ASCIZ |Search list empty|]
	ERLVL%,,[ASCIZ |SFD nest level too deep|]
	ERNCE%,,[ASCIZ |No-creates allowed in search list|]
	ERFCU%,,[ASCIZ |Can't update file|]
	ERENQ%,,[ASCIZ |File has outstanding locks set|]
	ERDDU%,,[ASCIZ |Device "down" and unusable|]
	ERDRS%,,[ASCIZ |Device is restricted|]
	ERDCM%,,[ASCIZ |Device controlled by MDA|]
	ERDAJ%,,[ASCIZ |Device allocated to another job|]
	ERIDM%,,[ASCIZ |Illegal I/O data mode|]
	ERNPC%,,[ASCIZ |No per-process space for extended channel|]
	ERNFC%,,[ASCIZ |No free channels available|]
	ERACR%,,[ASCIZ |Address check reading arguments|]
	ERACS%,,[ASCIZ |Address check storing answer|]
FOPESZ==.-FOPERR

; JOBPEK UUO errors
;
JPKERR:	JKNPV%,,[ASCIZ |No privileges|]
	JKIJN%,,[ASCIZ |Illegal job number|]
	JKSWP%,,[ASCIZ |Job swapped out or in transit|]
	JKIAD%,,[ASCIZ |Illegal address|]
	JKDNA%,,[ASCIZ |Data not addressable|]
	JKPNC%,,[ASCIZ |Page not in core|]
	JKIOE%,,[ASCIZ |I/O error|]
	JKABZ%,,[ASCIZ |Allocated but zero page|]
JPKESZ==.-JPKERR

; PAGE. UUO errors
;
PAGERR:	PAGUF%,,[ASCIZ |Unimplemented function|]
	PAGIA%,,[ASCIZ |Illegal argument|]
	PAGIP%,,[ASCIZ |Illegal page number|]
	PAGCE%,,[ASCIZ |Page can't exist but does|]
	PAGME%,,[ASCIZ |Page must exist but doesn't|]
	PAGMI%,,[ASCIZ |Page must be in core but isn't|]
	PAGCI%,,[ASCIZ |Page can't be in core but is|]
	PAGSH%,,[ASCIZ |Page is in a sharable high segment|]
	PAGIO%,,[ASCIZ |Paging I/O error|]
	PAGNS%,,[ASCIZ |No swapping space available|]
	PAGLE%,,[ASCIZ |Core limit exceeded|]
	PAGIL%,,[ASCIZ |Illegal if locked|]
	PAGNX%,,[ASCIZ |Cannot create allocated but zero page|]
	PAGNP%,,[ASCIZ |Not privileged|]
PAGESZ==.-PAGERR
; PATH. UUO errors
;
PATERR:	PTNSJ%,,[ASCIZ |No such job|]
	PTNAI%,,[ASCIZ |Number of arguments illegal|]
PATESZ==.-PATERR

; POKE. UUO errors
;
POKERR:	PKNPV%,,[ASCIZ |No privileges|]
	PKDIF%,,[ASCIZ |Old value doesn't match existing word|]
	PKBAD%,,[ASCIZ |Illegal address|]
POKESZ==.-POKERR
SUBTTL	AC save routines


; Save T1
;
SAVT1:	PUSH	P,T1			;SAVE T1
	PUSHJ	P,@-1(P)		;CALL THE CALLER
	  SKIPA				;NON-SKIP RETURN
	AOS	-2(P)			;ADJUST RETURN PC
	POP	P,T1			;RESTORE T1
	SUB	P,[1,,1]		;ADJUST STACK
	POPJ	P,			;RETURN


; Save T1 and T2
;
SAVT2:	ADD	P,[2,,2]		;ADJUST STACK
	DMOVEM	T1,-1(P)		;SAVE T1 AND T2
	PUSHJ	P,@-2(P)		;CALL THE CALLER
	  SKIPA				;NON-SKIP RETURN
	AOS	-3(P)			;ADJUST RETURN PC
	DMOVE	T1,-1(P)		;RESTORE T1 AND T2
	SUB	P,[3,,3]		;ADJUST STACK
	POPJ	P,			;RETURN


; Save T1, T2, and T3
;
SAVT3:	ADD	P,[3,,3]		;ADJUST STACK
	DMOVEM	T1,-2(P)		;SAVE T1 AND T2
	MOVEM	T3,0(P)			;SAVE T3
	PUSHJ	P,@-3(P)		;CALL THE CALLER
	  SKIPA				;NON-SKIP RETURN
	AOS	-4(P)			;ADJUST RETURN PC
	DMOVE	T1,-2(P)		;RESTORE T1 AND T2
	MOVE	T3,0(P)			;RESTORE T3
	SUB	P,[4,,4]		;ADJUST STACK
	POPJ	P,			;RETURN
; Save T1, T2, T3, and T4
;
SAVT4:	ADD	P,[4,,4]		;ADJUST STACK
	DMOVEM	T1,-3(P)		;SAVE T1 AND T2
	DMOVEM	T3,-1(P)		;SAVE T3 AND T4
	PUSHJ	P,@-4(P)		;CALL THE CALLER
	  SKIPA				;NON-SKIP RETURN
	AOS	-5(P)			;ADJUST RETURN PC
	DMOVE	T1,-3(P)		;RESTORE T1 AND T2
	DMOVE	T3,-1(P)		;RESTORE T3 AND T4
	SUB	P,[5,,5]		;ADJUST STACK
	POPJ	P,			;RETURN


; Save F
;
SAVEF:	PUSH	P,F			;SAVE F
	PUSHJ	P,@-1(P)		;CALL THE CALLER
	  SKIPA				;NON-SKIP RETURN
	AOS	-2(P)			;ADJUST RETURN PC
	POP	P,F			;RESTORE F
	SUB	P,[1,,1]		;ADJUST STACK
	POPJ	P,			;RETURN
SUBTTL	Literals


	LIT

MPHEND::!				;END OF THE HIGH SEGMENT
HGHSIZ==MPHEND-HGHORG			;LENGTH OF THE HIGH SEGMENT
SUBTTL	Data storage


	RELOC	0			;LOW SEGMENT

MAPARG::BLOCK	.MPMAX			;PLACE FOR PEOPLE TO PUT ARG BLOCKS

ZBEG:!					;START OF DATA TO ZERO

MAPDAT::BLOCK	.MPLEN			;DATA TABLE
CTXFLG:	BLOCK	1			;CONTEXT FLAG
USRACS:	BLOCK	20			;USER'S ACS
MAPPDL:	BLOCK	PDLSIZ			;INTERNAL PDL
TFFLAG:	BLOCK	1			;TRUE/FALSE FLAG
CPUTIM:	BLOCK	1			;USED FOR RUNTIM ACCUMULATION
ERRACS:	BLOCK	4			;ERROR ACS (T1 - T4)
ERRPC:	BLOCK	1			;ERROR PC
ERRNAM:	BLOCK	1			;NAME OF UUO
ERRTXT:	BLOCK	1			;ADDRESS OF UUO ERROR TEXT
POKBLK:	BLOCK	3			;POKE. UUO BLOCK
CPYBLK:	BLOCK	.CBXLN			;COPY BLOCK
JPKFLG:	BLOCK	1			;JOBPEK FLAG WORD

MAPFLG:	BLOCK	1			;MAPPING FLAGS
USRJOB:	BLOCK	1			;USER JOB NUMBER
UUOARG:	BLOCK	2			;UUO ARGUMENTS

HASHTA:	BLOCK	1			;HASH TABLE ADDRESS
HASHTL:	BLOCK	1			;HASH TABLE LENGTH
HASHCA:	BLOCK	1			;ADDRESS OF FIRST CHUNK
HASHCL:	BLOCK	1			;LENGTH OF CHUNK AREA
PAGCNT:	BLOCK	1			;COUNT OF AVAILABLE PAGES FOR MAPPING
CSHXCT:	BLOCK	1			;INSTRUCTION TO TEST PHYSICAL PAGE BIT
CSHPAG:	BLOCK	1			;FIRST PAGE NUMBER FOR MAPPING
CBHEAD:	BLOCK	.CBLEN			;CACHE BLOCK LIST HEADER
PAGFUN:	BLOCK	1			;FUNNY PAGE UPT OFFSET
PAGFLG:	BLOCK	1			;PAGE MAP ENTRY FLAG
PAGIDX:	BLOCK	1			;SECONDARY PAGE MAP INDEX

JOBN:	BLOCK	1			;NUMBER OF JOBS IN THE SYSTEM
SEGN:	BLOCK	1			;NUMBER OF SEGMENTS IN THE SYSTEM
KLPFLG:	BLOCK	1			;KL PAGING FLAG
EDVADR:	BLOCK	1			;EDV ADDRESS
EDVCNT:	BLOCK	1			;EDV COUNT WORD
EDVDAT:	BLOCK	1			;EDV FLAGS AND CPU DATA WORD
EPTADR:	BLOCK	1			;EPT ADDRESS
SPTADR:	BLOCK	1			;SPT ADDRESS
NUMTAB:	BLOCK	1			;POINTER TO NUMTAB IN THE MONITOR
RNGTAB:	BLOCK	1			;POINTER TO RNGTAB IN THE MONITOR
JBTSGN:	BLOCK	1			;POINTER TO JBTSGN IN THE MONITOR
JBTPDB:	BLOCK	1			;POINTER TO JBTPDB IN THE MONITOR
JBTADR:	BLOCK	1			;POINTER TO JBTADR IN THE MONITOR
JBTUPM:	BLOCK	1			;POINTER TO JBTUPM IN THE MONITOR
HIORG:	BLOCK	1			;MONITOR'S HIGH SEGMENT ORIGIN
HIFLAG:	BLOCK	1			;HIGH SEGMENT MAPPED FALG
HGHUEA:	BLOCK	1			;HIGHEST UNMAPPED EXEC ADDRESS
PPABEG:	BLOCK	1			;BEGINING PER-PROCESS ADDRESS
PPAEND:	BLOCK	1			;ENDING PER-PROCESS ADDRESS +1
GTBARG:	BLOCK	1			;GETTAB ARGUMENT
GTBNUM:	BLOCK	1			;NUMTAB ENTRY FOR CURRENT GETTAB
GTBIDX:	BLOCK	1			;INDEX INTO GETTAB DISPATCH TABLE
GTBRNG:	BLOCK	1			;LOWER,,UPPER LIMIT FOR RANGE

BYTPTR:	BLOCK	1			;BYTE POINTER
BYTCNT:	BLOCK	1			;BYTE COUNT
FILCHN:	BLOCK	1			;FILE CHANNEL NUMBER
IOLIST:	BLOCK	2			;IOWD
DIRADR:	BLOCK	1			;.EXE DIRECTORY ADDRESS
DIRPGS:	BLOCK	1			;NUMBER OF PAGES IN .EXE DIRECTORY
FOPBLK:	BLOCK	FOPSIZ			;FILOP. UUO BLOCK
LERBLK:	BLOCK	LERSIZ			;LOOKUP/ENTER UUO BLOCK
PTHBLK:	BLOCK	PTHSIZ			;PATH. UUO BLOCK
FILBLK:	BLOCK	FILSIZ			;BLOCK TO RETURN FULL FILESPEC
FILPPN:	BLOCK	1			;DEFAULT PPN

ZEND:!					;END OF DATA TO ZERO

SUBTTL	End


	END