-- SimStorageImpl.mesa
-- last edited by Suzuki: November 30, 1981  2:46 PM 

DIRECTORY
	AltoDefs,
	SegmentDefs,
	SimStorage,
	SimTsim;

SimStorageImpl: PROGRAM
	IMPORTS SegmentDefs
	EXPORTS SimStorage = { OPEN SimTsim;

restNode: CARDINAL ← 0;
originNode: LONG POINTER;
restTrans: CARDINAL ← 0;
originTrans: LONG POINTER;
restUsymbol: CARDINAL ← 0;
originUsymbol: LONG POINTER;
restWnode: CARDINAL ← 0;
originWnode: LONG POINTER;

VMPageUsed: PACKED ARRAY [0..AltoDefs.MaxVMPage] OF BOOLEAN;

AllocateNode: PUBLIC PROC RETURNS [ret: LONG POINTER] = { OPEN SegmentDefs;
	segment: DataSegmentHandle;
	IF restNode<SIZE[Node] THEN {
		restNode ← 1024;
		segment ← NewDataSegment[base: DefaultXMBase, pages: 4];
		MarkVMPage[segment, 4];
		originNode ← LongDataSegmentAddress[segment]};
	ret ← originNode;
	originNode ← originNode + SIZE[Node];
	restNode ← restNode - SIZE[Node];
	};

AllocateTrans: PUBLIC PROC RETURNS [ret: LONG POINTER] = { OPEN SegmentDefs;
	segment: DataSegmentHandle;
	IF restTrans<SIZE[Trans] THEN {
		restTrans ← 1024;
		segment ← NewDataSegment[base: DefaultXMBase, pages: 4];
		MarkVMPage[segment, 4];
		originTrans ← LongDataSegmentAddress[segment]};
	ret ← originTrans;
	originTrans ← originTrans + SIZE[Trans];
	restTrans ← restTrans - SIZE[Trans];
	};

AllocateUsymbol: PUBLIC PROC RETURNS [ret: LONG POINTER] = { OPEN SegmentDefs;
	segment: DataSegmentHandle;
	IF restUsymbol<SIZE[Usymbol] THEN {
		restUsymbol ← 1024;
		segment ← NewDataSegment[base: DefaultXMBase, pages: 4];
		MarkVMPage[segment, 4];
		originUsymbol ← LongDataSegmentAddress[segment]};
	ret ← originUsymbol;
	originUsymbol ← originUsymbol + SIZE[Usymbol];
	restUsymbol ← restUsymbol - SIZE[Usymbol];
	};

AllocateWnode: PUBLIC PROC RETURNS [ret: LONG POINTER] = { OPEN SegmentDefs;
	segment: DataSegmentHandle;
	IF restWnode<SIZE[Wnode] THEN {
		restWnode ← 1024;
		segment ← NewDataSegment[base: DefaultXMBase, pages: 4];
		MarkVMPage[segment, 4];
		originWnode ← LongDataSegmentAddress[segment]};
	ret ← originWnode;
	originWnode ← originWnode + SIZE[Wnode];
	restWnode ← restWnode - SIZE[Wnode];
	};

MarkVMPage: PROC [segment: SegmentDefs.DataSegmentHandle, pages: CARDINAL] = { 
	i: CARDINAL;
	FOR i IN [0..pages) DO
		VMPageUsed[segment.VMpage+i] ← TRUE
		ENDLOOP};

FreeNodes: PUBLIC PROC = { OPEN SegmentDefs;
	i: [0..AltoDefs.MaxVMPage];
	p: LONG POINTER;
	ds: DataSegmentHandle;
	FOR i IN [0..AltoDefs.MaxVMPage] DO
		IF VMPageUsed[i]=TRUE THEN {
			VMPageUsed[i] ← FALSE;
			p ← LongAddressFromPage[i];
			ds ← LongVMtoDataSegment[p];
			IF ds#NIL THEN DeleteDataSegment[ds]}
		ENDLOOP};

i: [0..AltoDefs.MaxVMPage];
FOR i IN [0..AltoDefs.MaxVMPage] DO
  VMPageUsed[i] ← FALSE
  ENDLOOP;
}.