//D1VM.bcpl // Procedures to manage the virtual memory on the record file and // the FastSearch procedure called by SearchBlocks. // Last edited: 17 December 1979 //VM mapping information is stored in two arrays broken into #2000-word //chunks stored on the record file. VAmem[VA] contains all information //about that VA (presently its AA and "Emulator" bit). AAmem[AA] contains //the top 7 bits of VA (or #377 if no corresponding VA), allowing //information for an AA to be determined by indexing into AAmem, then //searching at most 128 entries in VAmem. AA and VA buffers compete for //core storage with the symbol buffers managed by MSYM and MSYMOV. //All in core blocks are kept in BlockTable, described by the BT structure, //which has Dirty, Core, and Kind fields. The Sym, VA, and AA //structures also have auxiliary tables (HeadBlock, VAtab, and AAtab, //respectively) that give the BlockAddr in the record file associated //with that block. get "mcommon.d" get "d1.d" manifest [ get "d1regmem.d" ] external [ // OS SetBlock; Usc // MSYM GetBlock // MSYMOV MakeNewBlock // MMPRGN UpdateMPDValues // MCMD FormCmdMenu // D1TABLES @MEMLEN; @MEMNAM // D1CONFIG IMXmask // Defined here LookUpAA; LookUpVA; SetVirtP; RetrieveBlock; FastSearch @VirtualP; VAtab; AAtab IMstab; RMstab; BRstab; TASKNstab; DEVICEstab ] static [ VAtab; AAtab; @VirtualP IMstab; RMstab; BRstab; TASKNstab; DEVICEstab ] //Called both as an action and from D1Reset, D1Load, and D1I2. let SetVirtP(Flag,nil,nil; numargs NA) be [ VirtualP = Flag //Changed DefMemName to be "VM" always // DefMemName = MEMNAM!(Flag ? IMx,IMXx) if NA ge 2 do [ UpdateMPDValues(); FormCmdMenu() ] ] and RetrieveBlock(TablePtr,Kind,Strategy,Block,InitVal; numargs NA) = valof [ let Blk = nil if NA < 4 then Block = 0 test TablePtr!0 eq 0 ifso //If block doesn't exist [ if NA < 5 then resultis 0 //No such Block let B = MakeNewBlock(NPagesPerStandardBlock,Kind,Strategy,Block) TablePtr!0 = B>>BT.BlockAddr Blk = B>>BT.Core SetBlock(Blk,InitVal,BlockSize) ] ifnot Blk = (GetBlock(TablePtr!0,Kind,Strategy,Block))>>BT.Core resultis Blk ] //Note: An AA may be a 16-bit quantity, in which case bits larger than //the quantity of physical storage are thrown away by the hardware. //Consequently, before transforming an AA into a VA, unused high-order //bits are truncated. However, a VA of -1 is used to represent //not-in-VM, so not thrown away. //Return the VA corresponding to AA (#137777 if none); if the lvPtr arg is //provided, point this at the AA structure in core (only do this if there //is some VA corresponding to AA). and LookUpVA(AA,lvPtr; numargs NA) = valof [ AA = AA & IMXmask let Block = RetrieveBlock(AAtab+(AA rshift BlockShift),AAKind,4) if Block eq 0 then resultis -1 let AAPtr = Block+(AA & BlockMask) if NA ge 2 then rv lvPtr = AAPtr resultis AAPtr!0 & #137777 ] //Return the AA corresponding to VA; if the DVec argument is given, supply //full particulars (presently just the EMU bit) in DVec in IM format. //Returns negative if not in VM. and LookUpAA(VA,DVec; numargs NA) = valof [ let Val = -1 if Usc(VA,MEMLEN!(IMx+IMx+1)) < 0 do [ let Block = RetrieveBlock(VAtab+(VA rshift BlockShift),VAKind,1) if Block ne 0 then Val = Block!(VA & BlockMask) ] //**Temporary kludge until MicroD fixed if NA ge 2 then DVec!3 = (Val & #7777)+((Val & #140000) rshift 2) resultis Val & #137777 ] //Called from SearchBlocks in MSYM. Returns BlockTable pointer for the //block containing the nearest symbol le Addr in MemX, or 0 if don't know. and FastSearch(Addr,MemX) = valof [ let Block = 0 switchon MemX into [ case IMx: Block = RetrieveBlock(IMstab+((Addr & IMXmask) rshift (BlockShift+1)), IMKind,1) Addr = Addr & (BlockMask+BlockMask+1); endcase case RMx: Block = RMstab; endcase case BRx: Block = BRstab; endcase case TASKNx: Block = TASKNstab; endcase case DEVICEx: Block = DEVICEstab; endcase default: resultis 0 ] if (Addr ge MEMLEN!(MemX+MemX+1)) % (Block eq 0) then resultis 0 resultis GetBlock(Block>>Bytes.Byte^Addr,SymKind,1,Block) ]