PrincOpsUtils.mesa
last edited by Levin on August 8, 1983 11:44 am
Last Edited by: Birrell, July 8, 1983 1:16 pm
DIRECTORY
Basics USING [BITAND, BITSHIFT, LongNumber],
PrincOps USING [
aASSOC, aGETF, aRCLK, aSETF, aTEXTBLT, aVERSION, aZERO, BBptr, BBTableAlignment, BBTableSpace, ByteBltBlock, ControlLink, flagsVacant, FrameCodeBase, FrameHandle, FrameSizeIndex, FrameVec, GlobalFrameHandle, InterimPageState, LargeReturnSlot, LastAVSlot, MaxFrameSize, MDSreg, NullLink, PageCount, PageFlags, PageNumber, PageState, ProcessStateBlock, PsbHandle, PsbIndex, PSBreg, PTCreg, Queue, RealPageNumber, returnOffset, TextBltArg, TextBltArgAlignment, TextBltArgSpace, TextBltResult, Ticks, UnboundLink, VersionResult, WDCreg, wordsPerPage, XferTrapStatus, XTSreg, zALLOC, zBCAST, zBITBLT, zBLT, zBLTL, zDWDC, zFREE, zGADRB, zIWDC, zLADRB, zLLB, zME, zMISC, zMRE, zMXD, zMXW, zNOTIFY, zPOP, zPUSH, zREQUEUE, zRR, zSLB, zWR];
PrincOpsUtils: DEFINITIONS IMPORTS Basics =
BEGIN
OPEN PrincOps;
Note to the casual reader: Most of the definitions in this interface are intended for use by wizards. Only the first section "Utilities for Basic Data Structures" is likely to be useful to general clients. In general, clients should avoid procedures that aren't declared to be SAFE.
Utilities for Basic Data Structures
Conversion among various memory size measures
The following procedures are coded in an obscure way to avoid invoking software-implemented arithmetic. This will all go away when the commented code sequences are introduced (in Trinity).
PagesForWords: SAFE PROC [words: INT] RETURNS [pages: PageCount] = TRUSTED INLINE {
RETURN[Basics.DBITSHIFT[words, -logWordsPerPage]]
longA: Basics.LongNumber = [li[li: words+wordsPerPage-1]];
longB: Basics.LongNumber = [bytes[lh: longA.hl, ll: longA.lh, hh: 0, hl: longA.hh]];
RETURN[longB.li]
};
WordsForPages: SAFE PROC [pages: PageCount] RETURNS [words: INT] = TRUSTED INLINE {
RETURN[Basics.DBITSHIFT[pages, logWordsPerPage]]
longA: Basics.LongNumber = [li[li: pages]];
longB: Basics.LongNumber = [bytes[lh: longA.ll, ll: 0, hh: longA.hl, hl: longA.lh]];
RETURN[longB.li]
};
PagesForBytes: SAFE PROC [bytes: INT] RETURNS [pages: PageCount] = TRUSTED INLINE {
RETURN[Basics.DBITSHIFT[bytes, -logBytesPerPage]]
n: Basics.LongNumber ← [li[li: bytes+1]];
n ← [num[
lowbits: Basics.BITSHIFT[n.lowbits, -1] +
(IF Basics.BITAND[n.highbits, 1] = 1 THEN 100000B ELSE 0),
highbits: Basics.BITSHIFT[n.highbits, -1]
]];
RETURN[PagesForWords[n.li]]
};
BytesForPages: SAFE PROC [pages: PageCount] RETURNS [bytes: INT] = TRUSTED INLINE {
RETURN[Basics.DBITSHIFT[pages, logBytesPerPage]]
words: INT = WordsForPages[pages];
RETURN[words+words]
};
Conversion among various memory address measures
The following procedures are coded in an obscure way to avoid invoking software-implemented arithmetic. This will all go away when the commented code sequences are introduced (in Trinity).
AddressForPageNumber: UNSAFE PROC [page: PageNumber]
RETURNS [address: LONG POINTER] = INLINE {
RETURN[Basics.DBITSHIFT[page, logWordsPerPage]]
longA: Basics.LongNumber = [li[li: page]];
longB: Basics.LongNumber = [bytes[lh: longA.ll, ll: 0, hh: longA.hl, hl: longA.lh]];
RETURN[LOOPHOLE[longB.lc]]
};
PageNumberForAddress: SAFE PROC [address: LONG POINTER] RETURNS [page: PageNumber] = TRUSTED INLINE {
RETURN[Basics.DBITSHIFT[address, -logWordsPerPage]]
longA: Basics.LongNumber = LOOPHOLE[address];
longB: Basics.LongNumber = [bytes[lh: longA.hl, ll: longA.lh, hh: 0, hl: longA.hh]];
RETURN[longB.li]
};
Block copying utilities
LongMove: PROC [from: LONG POINTER, nwords: CARDINAL, to: LONG POINTER] = INLINE {
Trinity instructions will make this more efficient in the overlapping case.
Ordered: PROC [lp: LONG POINTER] RETURNS [LONG ORDERED POINTER] =
MACHINE CODE {};
IF Ordered[to] IN [Ordered[from]..Ordered[from]+nwords) THEN
FOR i: CARDINAL DECREASING IN [0..nwords) DO (to+i)^ ← (from+i)^; ENDLOOP
ELSE LongCopy[from: from, to: to, nwords: nwords];
};
COPY, Copy: PROC [from: POINTER, nwords: CARDINAL, to: POINTER] = MACHINE CODE
{zBLT};
ByteBlt: PROC [to, from: ByteBltBlock] RETURNS [nBytes: CARDINAL];
This will be a machine code procedure in Trinity.
LongCOPY, LongCopy: PROC [from: LONG POINTER, nwords: CARDINAL, to: LONG POINTER] =
MACHINE CODE {zBLTL};
Long Pointer Manipulation
LowHalf: PROC [u: LONG POINTER] RETURNS [POINTER] = INLINE
{RETURN[LOOPHOLE[LOOPHOLE[u, Basics.LongNumber].lowbits]]};
HighHalf: PROC [u: LONG POINTER] RETURNS [CARDINAL] = INLINE
{RETURN[LOOPHOLE[u, Basics.LongNumber].highbits]};
MakeLongPointer: PROC [low, high: CARDINAL] RETURNS [LONG POINTER] = MACHINE CODE
{};
Miscellaneous
ZERO, LongZero: PROC [where: LONG POINTER, nwords: CARDINAL] =
MACHINE CODE {zMISC, aZERO; zPOP; zPOP};
PUSH: PROC RETURNS [WORD] = MACHINE CODE {zPUSH};
GetClockPulses: SAFE PROC RETURNS [LONG CARDINAL] =
TRUSTED MACHINE CODE {zMISC, aRCLK};
VERSION: SAFE PROC RETURNS [VersionResult] =
TRUSTED MACHINE CODE {zMISC, aVERSION};
Utilities for BitBlt and TextBlt (wizards only)
AlignedBBTable: PROC [ip: POINTER TO BBTableSpace] RETURNS [b: BBptr] = INLINE {
align: TYPE = MACHINE DEPENDENT RECORD [
s: [0..WORD.LAST/BBTableAlignment), z: [0..BBTableAlignment)];
b ← LOOPHOLE[ip + BBTableAlignment - 1];
LOOPHOLE[b, align].z ← 0;
};
BITBLT: PROC [ptr: BBptr] = MACHINE CODE {zBITBLT};
AlignedTextBltArg: PROC [ip: POINTER TO TextBltArgSpace]
RETURNS [p: POINTER TO TextBltArg] = INLINE {
align: TYPE = MACHINE DEPENDENT RECORD [
s: [0..WORD.LAST/TextBltArgAlignment), z: [0..TextBltArgAlignment)];
p ← LOOPHOLE[ip + TextBltArgAlignment - 1];
LOOPHOLE[p, align].z ← 0;
};
TextBlt: PROC [
index: CARDINAL, bitPos: CARDINAL, micaPos: CARDINAL, count: INTEGER,
ptr: POINTER TO TextBltArg]
RETURNS [
newIndex: CARDINAL, newBitPos: CARDINAL, newMicaPos: CARDINAL,
newCount: INTEGER, result: TextBltResult] =
MACHINE CODE {zMISC, aTEXTBLT};
Utilities for Xfer data structures (wizards only)
Control links
GetReturnLink: PROC RETURNS [ControlLink] =
MACHINE CODE {zLLB, returnOffset};
SetReturnLink: PROC [ControlLink] =
MACHINE CODE {zSLB, returnOffset};
IsBound: SAFE PROC [link: UNSPECIFIED] RETURNS [BOOLEAN] = TRUSTED INLINE {
RETURN[link ~= UnboundLink AND link ~= NullLink]
};
Local Frames
GetReturnFrame: PROC RETURNS [FrameHandle] = LOOPHOLE[GetReturnLink];
SetReturnFrame: PROC [FrameHandle] = LOOPHOLE[SetReturnLink];
MyLocalFrame: PROC RETURNS [FrameHandle] =
MACHINE CODE {zLADRB, 0};
MakeFsi: SAFE PROC [words: [0..MaxFrameSize]] RETURNS [fsi: FrameSizeIndex] = TRUSTED INLINE {
FOR fsi IN [0..LastAVSlot) DO
IF FrameVec[fsi] >= words THEN RETURN;
ENDLOOP;
ERROR
};
FrameSize: SAFE PROC [fsi: FrameSizeIndex[0..LargeReturnSlot)]
RETURNS [[0..MaxFrameSize]] = TRUSTED INLINE {RETURN[FrameVec[fsi]]};
Global Frames
MyGlobalFrame: PROC RETURNS [GlobalFrameHandle] =
MACHINE CODE {zGADRB, 0};
GlobalFrame: SAFE PROC [link: --ControlLink--UNSPECIFIED] RETURNS [PROGRAM];
GlobalFrameAndEntryPoint: SAFE PROC [link: --ControlLink--UNSPECIFIED]
RETURNS [gf: GlobalFrameHandle, ep: CARDINAL];
Code segments
Codebase, CodeBase: PROC [frame: GlobalFrameHandle]
RETURNS [LONG POINTER --TO CSegPrefix--] = INLINE {
c: FrameCodeBase ← frame.code;
c.out ← FALSE;
RETURN[c.longbase]
};
Allocation Vector
Alloc: PROC [FrameSizeIndex] RETURNS [--FrameHandle--POINTER] =
MACHINE CODE {zALLOC};
Free: PROC [POINTER] = MACHINE CODE {zFREE};
Utilities for Process data structures (wizards only)
Process Data Area access
PsbHandleToIndex: SAFE PROC [handle: PsbHandle] RETURNS [PsbIndex] = TRUSTED INLINE {
RETURN[LOOPHOLE[handle, CARDINAL]/SIZE[ProcessStateBlock]]};
PsbIndexToHandle: SAFE PROC [index: PsbIndex] RETURNS [PsbHandle] = TRUSTED INLINE {
RETURN[LOOPHOLE[index*SIZE[ProcessStateBlock]]]};
Monitors and Condition Variables
Enter: PROC [POINTER TO MONITORLOCK] RETURNS [success: BOOLEAN] =
MACHINE CODE {zME};
LongEnter: PROC [LONG POINTER TO MONITORLOCK] RETURNS [success: BOOLEAN] =
MACHINE CODE {zME};
Exit: PROC [POINTER TO MONITORLOCK] =
MACHINE CODE {zMXD};
LongExit: PROC [LONG POINTER TO MONITORLOCK] =
MACHINE CODE {zMXD};
Wait: PROC [POINTER TO MONITORLOCK, POINTER TO CONDITION, --timeout:--CARDINAL] =
MACHINE CODE {zMXW};
LongWait: PROC [
LONG POINTER TO MONITORLOCK, LONG POINTER TO CONDITION, --timeout:--CARDINAL] =
MACHINE CODE {zMXW};
ReEnter: PROC [POINTER TO MONITORLOCK, POINTER TO CONDITION]
RETURNS [success: BOOLEAN] =
MACHINE CODE {zMRE};
LongReEnter: PROC [LONG POINTER TO MONITORLOCK, LONG POINTER TO CONDITION]
RETURNS [success: BOOLEAN] =
MACHINE CODE {zMRE};
Notify: PROC [POINTER TO CONDITION] =
MACHINE CODE {zNOTIFY};
LongNotify: PROC [LONG POINTER TO CONDITION] =
MACHINE CODE {zNOTIFY};
Broadcast: PROC [POINTER TO CONDITION] =
MACHINE CODE {zBCAST};
LongBroadcast: PROC [LONG POINTER TO CONDITION] =
MACHINE CODE {zBCAST};
Requeue: PROC [
from: LONG POINTER TO Queue, to: LONG POINTER TO Queue, p: PsbHandle] =
MACHINE CODE {zREQUEUE};
EnableAndRequeue: PROC [
from: LONG POINTER TO Queue, to: LONG POINTER TO Queue, p: PsbHandle] =
Note: this depends on having one instruction after enabling.
MACHINE CODE {zDWDC; zREQUEUE};
Interrupts
DisableInterrupts: PROC = MACHINE CODE {zIWDC};
EnableInterrupts: PROC = MACHINE CODE {zDWDC};
AllocateNakedCondition: PROC RETURNS [cv: LONG POINTER TO CONDITION, mask: WORD];
This procedure allocates one of the sixteen naked notify condition variables, initializes it with the default timeout, and returns a long pointer and wakeup mask with an appropriate bit set.
DeallocateNakedCondition: PROC [cv: LONG POINTER TO CONDITION];
This procedure deallocates a naked notify condition variable previously allocated with AllocateNakedCondition.
Utilities for Virtual Memory Map (wizards only)
ExchangePageState: PROC [virtual: PageNumber, newState: PageState]
RETURNS [oldState: PageState, real: RealPageNumber] = INLINE {
Gets the state and real page of a virtual page;
If the page is mapped, also sets the flags to newState.
DoExchangePageState: PROC [
virtual: --OldPageNumber--CARDINAL, state: InterimPageState]
RETURNS [oldState: InterimPageState] =
MACHINE CODE {zMISC, aSETF};
[logSingleError: , flags: oldState.flags, realPage: real] ←
DoExchangePageState[virtual, InterimPageState[FALSE, newState.flags, 0]].oldState;
};
ExchangePageFlags: PROC [virtual: PageNumber, newFlags: PageFlags]
RETURNS [oldState: PageState, real: RealPageNumber] =
Gets the state and real page of a virtual page;
If the page is mapped, also sets the flags to newFlags.
INLINE {RETURN ExchangePageState[virtual, PageStateFromFlags[newFlags]]};
GetPageState: PROC [virtual: PageNumber]
RETURNS [state: PageState, real: RealPageNumber] = INLINE {
Gets the state and real page of a virtual page.
DoGetPageState: PROC [virtual: --OldPageNumber--CARDINAL] RETURNS [state: InterimPageState] =
MACHINE CODE {zMISC, aGETF};
[logSingleError: , flags: state.flags, realPage: real] ← DoGetPageState[virtual].state;
};
SetPageState: PROC [virtual: PageNumber, real: RealPageNumber, state: PageState] = INLINE {
Sets the real page and state of a virtual page.
DoSetPageState: PROC [virtual: --OldPageNumber--CARDINAL, state: InterimPageState] =
MACHINE CODE {zMISC, aASSOC};
DoSetPageState[virtual, InterimPageState[FALSE, state.flags, real]];
};
SetPageFlags: PROC [virtual: PageNumber, real: RealPageNumber, flags: PageFlags] =
Sets the real page and flags of a virtual page.
INLINE {SetPageState[virtual, real, PageStateFromFlags[flags]]};
IsMapped: SAFE PROC [virtual: PageNumber] RETURNS [BOOL] =
TRUSTED INLINE {RETURN[GetPageState[virtual].state.flags ~= flagsVacant]};
IsVacant: SAFE PROC [virtual: PageNumber] RETURNS [BOOL] =
TRUSTED INLINE {RETURN[GetPageState[virtual].state.flags = flagsVacant]};
PageStateFromFlags: SAFE PROC [flags: PageFlags] RETURNS [PageState] =
TRUSTED INLINE {RETURN[LOOPHOLE[flags]]};
Miscellaneous (wizards only)
WriteMDS: PROC [mdsi: CARDINAL] =
MACHINE CODE {zWR, MDSreg};
ReadPSB: PROC RETURNS [currentProcess: PsbHandle] =
MACHINE CODE {zRR, PSBreg};
WritePSB: PROC [currentProcess: PsbHandle] =
MACHINE CODE {zWR, PSBreg};
ReadPTC: SAFE PROC RETURNS [time: Ticks] =
TRUSTED MACHINE CODE {zRR, PTCreg};
WritePTC: SAFE PROC [time: Ticks] =
TRUSTED MACHINE CODE {zWR, PTCreg};
ReadWDC: SAFE PROC RETURNS [countDisabled: CARDINAL] =
TRUSTED MACHINE CODE {zRR, WDCreg};
WriteWDC: PROC [countDisabled: CARDINAL] =
MACHINE CODE {zWR, WDCreg};
ReadATP, ReadOTP: PROC RETURNS [ControlLink] =
MACHINE CODE {zLLB, 3B};
ReadXTS: SAFE PROC RETURNS [XferTrapStatus] = TRUSTED MACHINE CODE {zRR, XTSreg};
WriteXTS: PROC [XferTrapStatus] = MACHINE CODE {zWR, XTSreg};
ReadXTP: PROC RETURNS [ControlLink] = MACHINE CODE {zLLB, 3};
END.