.mcall	.module
.module	XHANDL,version=9,comment=<Extended Memory Overlay Handler>,audit=NO,title=NO,ident=NO,lib=YES
	.sbttl	Extended Memory Overlay Handler
;+
;			Copyright (c) 1986
;			   C. E. Chew
;
; 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 the author.
;
; The author assumes no responsibility for the use or reliability of his
; software.
;
; Edit History:
;
; 09-Mar-87 CEC	Move low memory code around so that .audit won't
;		corrupt handler! Leave 40 (octal) bytes for .audit
; 22-Mar-87 CEC	Set syscom stack indication
;-
;+
; This code replaces the extended memory runtime overlay handler. This
; handler moves the root section into extended memory. The main code
; sequence is taken from overlay handler supplied with RT-11.
;-
;+
; The following code is included in the user's program by the
; linker whenever low memory overlays are requested by the user.
; The runtime low memory overlay handler is called by a dummy
; subroutine of the following form:
;
;	jsr	r5,$ovrh	;call to commmon code for low memory overlays
;	.word	<overlay #*6>	;# of desired segment
;	.word	<entry address>	;actual core address (virtual address)
;
; One dummy routine of the above form is stored in the resident portion
; of the user's program for each entry point to a low memory overlay segment.
; All references to the entry point are modified by the linker to be
; references to the appropriate dummy routine. Each overlay segment
; is called into core as a unit and must be contiguous in core. An
; overlay segment may have any number of entry points, to the limits
; of core memory. Only one segment at a time may occupy an overlay region.
;
; If overlays in extended memory are specified, the following dummy subroutine
; is used as the entry point to the extended memory overlay handler.
;
;	jsr	r5,$ovrhv	;entry for /v (extended memory) overlays
;	.word	<overlay #*6>	;# of desired segment
;	.word	<virtual entry address>	;virtual address of segment
;
; Additional data structures in the extended memory overlay handler and the
; overlay table permit use of extended memory, one region definition
; block is defined in the handler, and XM emt's are also included. Window
; definition blocks for the extended memory partitions follow the dummy
; subroutines in the overlay table.
;
; There is one word prefixed to every overlay region that identifies the
; segment currently resident in that overlay region. This word is an index
; into the overlay table and points at the overlay segment information.
;
; Undefined globals in the overlay handler must be named "$OVDF1" to
; "$OVDFn" such that a range check may be done by link to determine if
; the undefined globabl name is from the overlay handler. A check is
; done on the .rad50 characters "$OV", and then a range check is done on
; the .rad50 characters "DF1" to "DFn". These global symbols do not appear
; on link maps, since their value is not known until after the map has been
; printed. Currently $OVDF1 to $OVDF5 are in use.
;
; Globals symbols V$READ and V$DONE are useful when debugging overlaid
; programs.
;
;	V$READ:: will appear in the link map and locates the .READW
;	statement in the overlay handler.
;
;	V$DONE:: will appear in the link map and locates the first
;	instruction after the .READW in the overlay handler.
;-
	.mcall	.wdbdf .rdbdf .print .exit .readw ..v1..
	.mcall	.assume
	..v1..				;v1 format
	.wdbdf				;define wdb offsets
	.rdbdf				;define rdb offsets
;
usersp	=: 42				;job initial stack
jsw	=: 44				;job status word
userto	=: 50				;user high limit
bitmap	=: 360				;load bitmap
;
	.dsabl	gbl
	.globl	$ovdf1 $ovdf2 $ovdf3 $ovdf4 $ovdf5
	.globl	v$start v$stack v$jsw
	.sbttl	SYSCOM Setup
;+
; This forces RT11 to consider the overlay handler only as the root
; segment. The user's root segment is loaded into extended memory
; as an extended memory overlay. This is achieved by enlarging the
; region allocated for extended memory overlays.
;-
	.asect
.	= jsw
	.word	<3000 ! v$jsw>		;overlaid, virtual and load asect
;
.	= userto
	.word	$ovrhe - 2		;make a fake root segment
;
.	= bitmap
	.byte	300			;fake a bitmap
	.byte	0, 0, 0, 0, 0, 0, 0
	.byte	0, 0, 0, 0, 0, 0, 0, 0
	.sbttl	Overlay Handler Code
	.asect
	.enabl	lsb
;+
; Initial entry point. This code sets up the real root section in extended
; memory, clears any low memory overlay regions, sets up the stack and
; starts the program proper. It may be necessary to create the extended
; memory overlay region since there may not be any real extended memory
; overlays.
;-
.	= 150
$ovrhx::
	tst	#<$ovdf5-$ovdf4>
	bne	10$			;region exists
	mov	#area,r0		;get the argument list
	emt	375			;create a region
	bcc	10$
;
	jsr	r1,200$
	.asciz	/creating region/
	.even
;
10$:	jsr	r5,$ovrhv		;start up program
	.word	$ovrhs - <$ovtab - 6>
	.word	20$
;
20$:	mov	v$start,r3		;retrieve entrypoint location
	bne	30$
;
	jsr	r1,200$
	.asciz	/locating entry point/
	.even
;
30$:	mov	$vdf1,r1		;clear low memory overlay area
40$:	cmp	r1,$vdf2
	bhis	50$
	clr	(r1)+
	br	40$
;
50$:	mov	#$ovtab-4,r5		;start with first overlay
	mov	(pc)+,@(pc)+		;conditionally load overlays
	 bne	170$-160$+.
	 .word	160$
60$:	add	#6,70$			;proceed to next overlay entry
	cmp	(r5)+,(r5)+
	bit	#1,(r5)
	bne	80$			;end of overlay table
	cmp	(r5)+,#$ovdf5
	bhis	60$			;must be low memory overlay
	jsr	r5,$ovrhv		;read in extended memory overlay
70$:	.word	0			;overlay entry
	.word	60$
;
.assume	. le 360			;don't overrun bitmap
;
.	= 400
80$:	mov	(pc)+,@(pc)+		;replace initialisation code
	 mov	(r5),r1
	 .word	110$
	mov	(pc)+,@(pc)+
	 cmp	(r5)+,(r2)
	 .word	150$
	mov	(pc)+,@(pc)+
	 beq	170$-160$+.
	 .word	160$
;
	mov	v$stack,r1		;set up stack
	beq	90$
	mov	r1,sp			;set stack pointer
	mov	r1,@#usersp		;set syscom stack pointer
;
90$:	jmp	(r3)			;jump to entrypoint
;
$ovrhs::
	.word	xwindow, 20, <$ovdf1-$vdf5>/2
;
xwindow:.byte	0			;w.nid
	.byte	1			;w.napr
	.word	0			;w.nbas
	.word	<$ovdf2-$vdf5+77>/100	;w.nsiz
	.word	177777			;w.nrid
	.word	$ovdf3			;w.noff
	.word	<$ovdf2-$vdf5+77>/100	;w.nlen
	.word	ws.map			;w.nsts
;
xregion:.word	0			;three word region definition block
	.word	$ovdf3 + <<$ovdf2-$vdf5+77>/100> ;size of region
	.word	0			;region status
;
.assume	. le 500			;don't overrun chain area
;+
; There are two entry points to the overlay handler - $OVRHV, for /v
; (extended memory) overlays, and $OVRH for /o (low memory) overlays.
;-
	.psect	$ohand gbl
$ovrhv::
	inc	(pc)+			;set /v overlay switch
100$:	.word	0
;
$ovrh::
	mov	r0,-(sp)		;save registers
	mov	r1,-(sp)
	mov	r2,-(sp)
;
110$:	mov	(r5)+,r1		;pick up overlay number
;	mov	(r5),r1			;pick up overlay number
	add	#$ovtab-6,r1		;calculate table address
	mov	(r1)+,r2		;get first arg. of overlay seg. entry
	tst	100$
	beq	150$			;/o overlay being processed
;+
; Virtual overlay segments in the same region but in different partitions
; use different wdb's. Only one of these windows exists at any time.
; This is because when a new window in a virtual overlay region is created,
; the monitor implicitly eliminates any window that exists in that
; virtual overlay region. Thus, if the called overlay segment is not
; currently mapped, its window must be re-created (.CRAW'ed) besides
; being mapped. The mapping is done implicitly in the following code
; since the ws.map bit is set in all the virtual overlay segment's
; wdb's.
;-
120$:	tstb	(r2)			;do we need to create a window?
	beq	130$			;yes
	mov	@w.nbas(r2),r0		;get index of segment now mapped
	beq	130$			;no segment, must create a window
	cmp	$ovtab-6(r0),r2		;is overlay region same as this one?
	beq	140$			;if equal, just worry about disk IO
130$:	mov	#area+2,r0		;point to emt argument block + 2
	mov	r2,(r0)			;stuff address of wdb in emt area
	mov	#30.*^o400+2,-(r0)	;stuff .craw code
	emt	375			;do the emt
	bcs	190$			;carry set means error
140$:	mov	w.nbas(r2),r2		;get memory address
;+
; The .READW arguments are as follows:
; channel number, core address, length to read, relative block on disk.
; These are used in reverse order from that specified in the call.
;-
150$:	tst	(r2)			;see if overlay in place
;	cmp	(r5)+,(r2)		;see if overlay already resident
160$:	nop				;force root to be loaded
;	bne	170$			;someone already there
;	beq	170$			;already resident
v$read::
	.readw	17 r2 (r1) (r1)+	;read from overlay file
v$done::
	bcs	180$
170$:	mov	(sp)+,r2		;restore user's registers
	mov	(sp)+,r1
	mov	(sp)+,r0
	mov	(r5),r5			;get entry address
	clr	100$			;set up for /o overlay
	rts	r5			;enter overlay routine, restore r5
;
180$:	emt	376			;system error 10 (overlay IO)
	.byte	0, 373
;
190$:	jsr	r1,200$
	.asciz	/windowing to overlay/
	.even
;
200$:	.print	#msgpre
	.print	r1
	.exit
;
	.dsabl	lsb
	.sbttl	Impure Area
;
msgpre:	.ascii	/?XHANDL-F-Error /<200>
	.even
;
area:	.word	30.*^o400+0		;assume create region
	.word	xregion
;
$ovrhe::.blkb	20000 - 1000 - <. - $ovrhv>
	.sbttl	Extended Memory Root Section
;
$vdf5::	.word	$ovdf5			;point to word after wdb's in $ovtab
$vdf4::	.word	$ovdf4			;point to start of wdb's in $ovtab
;
rgadr:	.word	0			;three word region definition block
rgsiz:	.word	$ovdf3 + <<$ovdf2-$vdf5+77>/100> ;size of region
	.word	0			;region status
;
$vdf1::	.word	$ovdf1			;high addr root seg. + 2 (nxt avail)
$vdf2::	.word	$ovdf2			;high addr /o overlays + 2 (nxt avail)
	.sbttl	Overlay Table
;+
; Overlay table structure:
;
; loc 64 ->	$ovtab:
;		.word	<core addr>,<relative blk>,<word count>	;/o overlays
; loc 66 ->	.word	<wdb addr>,<relative blk>,<word count>	;/v overlays
;		dummy subroutines for all overlay segments
; $vdf4 ->	window definition blocks for extended memory overlays (/v)
; $vdf5 ->	word after the end of the window definition blocks (/v)
;-
	.psect	$otabl d gbl ovr
$ovtab::
;
	.end	$ovrhx
