	.title	PDPMEM	memory managemanet for PDP-11 version of 'C' ted



;	Edits:
;
;	16-JAN-1986 12:23  Brian Nelson
;
;	 (1) Raise region size to 18KW
;	 (2) Give window 1 4KW for index
;	 (3) Add MAPMAC() to map macro buffers to the region
;
;	02-Jul-86  17:02:33 Brian Nelson
;
;	 (1) Add second region for buffering work file if I/D task
;	     This is selected by GBLDEF=IDSPAC:1
;        (2) Reduce size of first region by 4KW if we use two regions.



	.psect	winmap	,rw,d,lcl,rel,con
	.psect	wincod	,ro,i,lcl,rel,con

	EXTEND	=	0

	.if eq	,EXTEND
	.ift

	.mcall	rdbdf$	,wdbdf$
	.mcall	atrg$s	,craw$s	,crrg$s	,map$s	,umap$s	,exit$s
	.mcall	feat$s	,tfea$s

	.MACRO	TFEA$S	FEAT,ERR
	.MCALL	MOV$,DIR$
	MOV$	FEAT
	MOV	(PC)+,-(SP)
	.BYTE	209.,2.
	DIR$	,ERR
	.ENDM

	FE$FMP	=	73
	T4$FMP	=	50

	rdbdf$
	wdbdf$

	.psect	winmap

fmap:	.word	0			; If fast mapping is available
mapcnt::.word	0			; Stats
highmap:.word	0			; where in region are we mapped at?
indcre:	.byte	0,0,0,0
fmt:	.asciz	/MAP error %d/<12>
craw:	.asciz	/%o %o/<12>
	.even

;	KW, number of Kwords to allocate in region
;	4KW for workfile cacheing
;	8KW for window 0 index
;	4KW for window 1 index
;	2KW for macro buffers

	KW = 4 + <2*4> + 4 + 2
	KWID = KW - 4

regdsc:	.word	0			; region id returned
	.word	40*KW			; 18 kw for now
	.word	0			; noname for region
	.word	0			; noname for region
	.word	0			; same parition
	.word	0			; same parition
	.word	RS.RED!RS.WRT!RS.ATT	; attach + read + write
	.word	^C377			; no world or group access

windsc:	.byte	0			; return the window id
	.byte	5			; apr 5 please (120000-140000)
	.word	0			; base virtual address returned
	.word	40*4			; 4kw window size
	.word	0			; fill in region id
	.word	0			; offset into region
	.word	40*4			; map all of it
	.word	WS.MAP!WS.EXT!WS.WRT!WS.RED ; read, extend and write
	.word	0			; sen/receive buffer address

idregd:	.word	0			; region id returned
	.word	40*4			; 4 kw for now
	.word	0			; noname for region
	.word	0			; noname for region
	.word	0			; same parition
	.word	0			; same parition
	.word	RS.RED!RS.WRT!RS.ATT	; attach + read + write
	.word	^C377			; no world or group access

idwind:	.byte	0			; return the window id
	.byte	4			; apr 6 please (140000-160000)
	.word	0			; base virtual address returned
	.word	40*4			; 4kw window size
	.word	0			; fill in region id
	.word	0			; offset into region
	.word	40*4			; map all of it
	.word	WS.MAP!WS.EXT!WS.WRT!WS.RED ; read, extend and write
	.word	0			; sen/receive buffer address

	.psect	wincod

crewin::feat$s	#FE$FMP			; Will fast mapping work?
	bcs	10$			; No
	cmpb	@#$DSW	,#IS.SET	; Is this supported?
	bne	10$			; No
	tfea$s	#T4$FMP			; Do have have fast mapping here?
	bcs	10$			; No
	cmpb	@#$DSW	,#IS.SET	; Yes, but is it enabled?
	bne	10$			; No, ignore
	mov	sp	,fmap		; Yes, say so.

10$:	tst	#idspac			; I/D space version?
	beq	20$			; No
	crrg$s	#idregdsc		; Yes, create the region please
	bcs	90$			; It's dedicated to buffering
	mov	r.gid+idregdsc,w.nrid+idwindsc
	craw$s	#idwindsc
	bcs	90$			; failed, exit please
	mov	r.gid+idregdsc,w.nrid+idwindsc
	mov	#WS.WRT	,w.nsts+idwindsc; do a map next (redundant)
	clr	w.noff+idwindsc		; offset zero from region start
	mov	#40*4	,w.nlen+idwindsc; amount to map
	map$s	#idwindsc		; do it please
	bcs	90$			; exit
	mov	#40*KWID,regdsc+2	; Reset the other region's size
					;

20$:	crrg$s	#regdsc			; create the region please
	bcs	90$			; failed
	mov	r.gid+regdsc,w.nrid+windsc
	craw$s	#windsc
	bcs	90$			; failed, exit please
	mov	#WS.WRT	,w.nsts+windsc	; do a map next (redundant)
	mov	#-1	,highmap	; no index mapped yet
	map$s	#windsc			; do it please
	bcs	90$			; exit
	inc	mapcnt			; Stats
	mov	#1	,r0
	return
90$:	movb	@#$DSW	,r0
	return

mapcac::tst	#idspac			; I/D space version?
	bne	10$			; Yes, don't need to map it.
	mov	#-1	,highmap
	mov	r.gid+regdsc,w.nrid+windsc
	mov	#WS.WRT	,w.nsts+windsc	; do a map next (redundant)
	clr	w.noff+windsc		; offset zero from region start
	mov	#40*4	,w.nlen+windsc	; amount to map
	map$s	#windsc			; do it please
	bcs	90$			; oops
	inc	mapcnt			; Stats
10$:	mov	#1	,r0		; success, exit
	return				; bye
90$:	movb	@#$DSW	,r0		; error, return the error code
	return


unmapc::tst	#idspac			; I/D space version. If so, we
	bne	20$			; Yes, exit.
	mov	r.gid+regdsc,w.nrid+windsc ; don't need to remap.
	mov	#WS.WRT	,w.nsts+windsc	; do a map next (redundant)
	mov	#40*4	,w.noff+windsc	; offset 4kw from region start
	mov	#40*4	,w.nlen+windsc	; amount to map
	clr	highmap			; indicate which part of index mapped
	tst	fmap			; Will fast mapping function?
	beq	10$			; No
	mov	#100050	,r0		; Yes, setup for fast mapping
	mov	#40*4	,r1		; Offset
	mov	#40*4	,r2		; Size
	iot				; Try it out
	tst	r0			; Successful?
	bpl	20$			; Yes.
					;
10$:	map$s	#windsc			; do it please
	bcs	90$			; oops
	inc	mapcnt			; Stats
20$:	mov	#1	,r0		; success, exit
	return				; bye
90$:	movb	@#$DSW	,r0		; error, return the error code
	jmp	maperr			;*********** TEMP
	return

	.endc				; if EQ, EXTEND


	.sbttl	allocate memory for index

	.if eq	,EXTEND			; mapping to a region for buffering
	.ift

mapmac::mov	r1	,-(sp)		; save it
	cmp	highmap	,#3		; Mapped already?
	beq	10$			; Yes, don't bother then
	mov	#3	,highmap	; Not mapped to index anymore
	mov	#40*2	,w.nlen+windsc	; amount to map
	mov	#40*20	,w.noff+windsc	; offset 16kw from region start
	tst	#idspac			; I/D space?
	beq	5$			; No
	mov	#40*14	,w.noff+windsc	; Yes,offset 12kw from region start
5$:	map$s	#windsc			; do it please
	bcs	maperr			; oops
	inc	mapcnt			; Stats
10$:	mov	4(sp)	,r1		; macro buffer number
	mul	#1000	,r1		; buffers are 512 bytes in size
	mov	#120000	,r0		; base address of the window
	add	r1	,r0		; offset into the window
	mov	(sp)+	,r1		; pop saved r1
	return				; back to caller now

mapwin::mov	2(sp)	,r0		; get offset into index to return
	tst	w			; which window are we working on?
	beq	20$			; file window number zero

	cmp	highmap	,#2		; already mapped correctly?
	beq	10$			; yes, skip the remap
	mov	#40*4	,w.nlen+windsc	; amount to map
	mov	#40*14	,w.noff+windsc	; offset 12kw from region start
	tst	#idspac			; I/D space?
	beq	5$			; No
	mov	#40*10	,w.noff+windsc	; Yes,offset 8kw from region start
5$:	map$s	#windsc			; do it please
	bcs	maperr			; oops
	inc	mapcnt			; Stats
	mov	#2	,highmap	; show that we are not mapped to low
10$:	br	50$			; and return the address

20$:	cmp	r0	,#3777		; is there room for this in first 4kw?
	blos	40$			; yes
	sub	#4000	,r0		; no, map up to next 4kw boundary
	cmp	highmap	,#1		; already mapped here ?
	beq	30$			; yes, skip the remap
	mov	#40*4	,w.nlen+windsc	; amount to map
	mov	#40*10	,w.noff+windsc	; offset 8kw from region start
	tst	#idspac			; I/D space?
	beq	35$			; No
	mov	#40*4	,w.noff+windsc	; Yes, offset 4kw from region start
35$:	map$s	#windsc			; do it please
	inc	mapcnt			; Stats
	mov	#1	,highmap	; show that we are not mapped to low
30$:	br	50$			; and return the address

40$:	tst	highmap			; mapped to the low 4kw of index ?
	beq	50$			; yes
	mov	#40*4	,w.noff+windsc	; no, remap to the low 4k area of index
	mov	#40*4	,w.nlen+windsc	; amount to map
	tst	#idspac			; I/D space version?
	beq	45$			; No
	clr	w.noff+windsc		; Yes, start mapping at the start.
45$:	map$s	#windsc			; do it please
	inc	mapcnt			; Stats
	clr	highmap			; say we are already mapped
50$:	asl	r0			; each entry is 2 words in size
	asl	r0
	add	#120000	,r0
	return

maperr:	movb	@#$DSW	,r0
	mov	r0	,-(sp)
	mov	#fmt	,-(sp)
	call	xprintf
	exit$s


getvm::	clr	r0			; failure (?)
	mov	4(sp)	,r1		; window number to allocate
	tstb	indcre(r1)		; already cbeen called ?
	bne	100$			; yes, die
	tst	r1			; which window are we doing
	beq	10$			; main one
	mov	#<4000*4>/4,@6(sp)	; alternate index
	br	20$
10$:	mov	#<4000*10>/4,@6(sp)	; size of index (8kw)
20$:	mov	#120000	,r0		; base of apr5 mapping
	incb	indcre(r1)		; remember that we were called already
100$:	return

allbuf::mov	#4*4	,@2(sp)
	mov	#120000	,r0
	tst	#idspac
	beq	100$
	mov	#100000	,r0
100$:	return

	.endc				; if eq, EXTEND


	.sbttl	allocate memory for index

	.if ne	,EXTEND
	.ift

;	Note: Old method via extk$s
;
;	char *getvm(size_of_block,block_number,&amount_allocated)
;
;	Request size is in number of index blocks. Each index block
;	is 4 bytes for the PDP-11.


	.mcall	extk$s	,gtsk$s
	.save
	.psect	rwdata
	.even
vmbase:	.word	0
vmtop:	.word	0
vmalloc:.word	0
	.psect	index	,rw,d,gbl,rel,ovr
windex::.word	0,0			; extra at top of task
	.restore

getvm::	tst	vmbase			; do we have anything yet ?
	bne	10$			; yes
	sub	#40	,sp		; no, do a gtsk$s to find it out
	mov	sp	,r1		; point to the buffer
	gtsk$s	r1			; get task info
	mov	g.tsts(r1),r1		; get task image size
	bic	#1	,r1		; insure even
	mov	#windex	,vmbase		; save base address of this then
	mov	r1	,vmtop		; save top address also
	add	#40	,sp		; pop buffer
10$:	mov	2(sp)	,r1		; number of entries to allocate
	sub	vmalloc	,r1		; less what we already allocated
	mul	#4	,r1		; size of allocation in bytes
	ash	#-6	,r1		; size of allocation in 32 word chunks
	bic	#^c77	,r1		; drop any bits propagated over
	extk$s	r1			; request from exec
	bcs	90$			; it failed
	ash	#6	,r1		; convert back to number of bytes all
	clr	r0			; and convert back to number of entries
	div	#4	,r0		; and return the count
	mov	r0	,@6(sp)		; send it back to caller
	add	r0	,vmalloc	; keep track of allocation so far
	mov	vmbase	,r0		; return base address also
	br	100$			; exit

90$:	clr	r0			; error exit, return address of zero
100$:	return				; exit

	.endc				; if ne, EXTEND


	.sbttl	allocate buffering for the work file

	.if ne	,EXTEND
	.ift

;	char *allbuffer(&n_allocated,min_number,max_number)
;
;	Allocate cache for disk workfile buffering. At some point
;	later we  will create a dynamic region  (if a free apr is
;	around) and write a new cacher to dynamically map things.
;	It returns the number of 512 byte blocks allocated.

	.save
	.psect	rwdata
cache:	.blkb	1000*4
	.restore

allbuffer::
	mob	#4	,@2(sp)
	mov	#cache	,r0
	return


mapcache::
unmapcache::
mapwin::
	return

	.endc				; if ne, EXTEND



	.end
