// IfsVMemInit.bcpl - once only code
// Copyright Xerox Corporation 1979, 1982

// Last modified September 17, 1982  4:14 PM by Taft

get "IfsVMem.decl"

external
[
// outgoing procedures
InitVMem

// incoming procedures
Allocate; SysErr; Noop; FalsePredicate; Zero

// incoming statics
vmdt; vmStats; sysZone
]

//----------------------------------------------------------------------------
let InitVMem() be
//----------------------------------------------------------------------------
// Note that no buffers are made available to the VMem package
// The caller must do that after calling this procedure
[
// Initialize the VMem package
let hMap = Allocate(sysZone, lenHMap, 0, true)
(table  //initialize vmem microcode
   [
    #55001	// sta 3 1 2
    #35003	// lda 3 3 2
    #74000	// initVMem
    #35001	// lda 3 1 2
     #1401	// jmp 1 3
   ])(hMap, lenHMap, 0)
InitializeVmem(hMap, lenHMap,  //Hash Map
 Allocate(sysZone, 256),  //buffer table
 Allocate(sysZone, lenLT), lenLT)  //lock table

// Initialize the VMD table.
// Note that it must always contain "zero" and "infinity" entries.
vmdt = Allocate(sysZone, lenVMDT)
let vmi = Allocate(sysZone, lenVMI)
vmi>>VMI.DOPAGEIO = SysErr
vmi>>VMI.CleanupLocks = Noop
vmi>>VMI.PageType = SysErr
vmi>>VMI.PageGroupAlign = SysErr
vmi>>VMI.PageGroupBase = SysErr
vmi>>VMI.PageGroupSize = SysErr
let vmd = Allocate(sysZone, 2*lenVMD)
vmd>>VMD.base = 0
vmd>>VMD.length = 4
vmd>>VMD.vmi = vmi
vmdt>>VMDT.vmd↑1 = vmd
vmd = vmd+lenVMD
vmd>>VMD.base = -8  //reserved by vMem package
vmd>>VMD.length = 8
vmd>>VMD.vmi = vmi
vmdt>>VMDT.vmd↑2 = vmd
vmdt>>VMDT.length = 2

vmStats = Allocate(sysZone, lenVMStats)
Zero(vmStats, lenVMStats)
]

// Derived from VMem package, by P. Deutsch:
// VMEMINIT -- initialize VMEM
// last edited August 1, 1977  1:48 PM

and InitializeVmem(HM, HMSIZE, BPTAB, LCL, LLCL) be
[

	get "vmem.d"

external	// procedures
[		// O.S.
	TruePredicate
	CallSwat
	SetBlock
		// VMEM
	LockOnly; LockZero
		// VMEMA
	REHASHMAP
]

external	// statics
[		// VMEM
	@HASHMAP; @HASHMAPSIZE; @HASHMAPMASK
	@HASHMAPSIZE2
	@HASHMAP1
	@HASHMAPTOP
	@Bpt; @BptLast
	EMPTYXX
	NAXX
	LockedCells; EndLockedCells; LastLockedCell
]


	if (HMSIZE & (HMSIZE-1)) ne 0 then
	   CallSwat("Bad HMAPSIZE -- InitializeVmem")
	HASHMAP, HASHMAPSIZE = HM+(HM&1), HMSIZE
	HASHMAPMASK = HASHMAPSIZE-2
	HASHMAPSIZE2 = HMSIZE rshift 1
	HASHMAP1 = HASHMAP+HMflagOffset
	HASHMAPTOP = HASHMAP+HASHMAPSIZE
	Bpt, LockedCells, EndLockedCells =
	  BPTAB, LCL, LCL+(LLCL & not 1)-LCsize
	LastLockedCell = LCL
	Zero(HASHMAP, HASHMAPSIZE)
	let dummypage(vp, bits) = valof
	 [ let hp = REHASHMAP(vp)
	   hp>>HM.NKEY = not vp
	   hp>>HM.FLAGWD = bits
	   resultis (hp-HASHMAP) lshift 7
	 ]
	EMPTYXX = dummypage(EmptyVP, CLEANbit+NOTREFbit+DUMMYbit)
	NAXX = dummypage(NaVP, CLEANbit+NOTREFbit+DUMMYbit)
	SetBlock(Bpt, NAXX, BptSize)
	@Bpt = 0; BptLast = 0
	LockOnly = FalsePredicate
	LockZero = TruePredicate
]