-- RTCommon.Mesa
-- last edited May 20, 1982 10:15 am by Paul Rovner

DIRECTORY
  Inline USING[LowHalf, HighHalf, BITSHIFT, LongNumber, BITOR, BITAND],
  RTBasic USING[Pointer, Address];

RTCommon: DEFINITIONS
  IMPORTS Inline
= BEGIN
  OPEN Inline, RTBasic;


-- TYPEs

  Field: TYPE = RECORD[bitFirst: [0..15], bitCount: [0..32]];


-- Constants

  LMasks: ARRAY [0..16] OF WORD =
    [0, 100000B, 140000B, 160000B, 170000B, 174000B, 176000B, 177000B,
     177400B, 177600B, 177700B, 177740B, 177760B, 177770B, 177774B, 177776B, 177777B];

  RMasks: ARRAY [0..16] OF WORD =
    [0, 1, 3, 7, 17B, 37B, 77B, 177B, 377B, 777B,
     1777B, 3777B, 7777B, 17777B, 37777B, 77777B, 177777B];


-- Procedures

  RepPtrAddr: PROC[ptr: Pointer] RETURNS[Address] = INLINE
    {RETURN[LOOPHOLE[ptr]]};
  RepAddrPtr: PROC[addr: Address] RETURNS[Pointer] = INLINE
    {RETURN[LOOPHOLE[addr]]};
  RepAddrRef: PROC[addr: Address] RETURNS[REF ANY] = INLINE
    {RETURN[LOOPHOLE[addr]]};

  FetchField: PROC[ptr: Pointer, field: Field] RETURNS[CARDINAL] = INLINE
   {OPEN field;
    RETURN[BITSHIFT[BITSHIFT[ptr↑, bitFirst], bitCount-16]]};

  FetchFieldLong: PROC[ptr: Pointer, field: Field] RETURNS[LONG CARDINAL] = INLINE
   {OPEN field;
    IF bitFirst+bitCount <= 16 THEN RETURN[FetchField[ptr, field]]
    ELSE RETURN[
	MakeLongCardinal[ptr↑, FetchField[ptr+1, [bitFirst: bitFirst, bitCount: bitCount-16]]]]};

  MakeLongCardinal: PROCEDURE[lo, hi: CARDINAL] RETURNS[lc: LONG CARDINAL] = INLINE
   {LOOPHOLE[lc, num LongNumber] ← [num[highbits: hi, lowbits: lo]]};


  StoreField: PROC[ptr: Pointer, field: Field, newValue: CARDINAL] = INLINE
   {OPEN field;
    bitOffset: [0..16] = 16-(bitFirst+bitCount);
    ptr↑ ← BITOR[ BITAND[ptr↑, LMasks[bitFirst]+RMasks[bitOffset]],
	           BITSHIFT[BITAND[newValue, RMasks[bitCount]], bitOffset]]};

  StoreFieldLong: PROC[ptr: Pointer, field: Field, newValue: LONG CARDINAL] = INLINE
   {OPEN field;
    IF bitFirst+bitCount <= 16
     THEN StoreField[ptr, field, LowHalf[newValue]]
     ELSE
      {ptr↑ ← LowHalf[newValue];
       StoreField[ptr+1, [bitFirst: bitFirst, bitCount: bitCount-16], HighHalf[newValue]]}};

  ShortenLongCardinal: PROC[lc: LONG CARDINAL] RETURNS[CARDINAL] = INLINE
   {IF HighHalf[lc] # 0 THEN ERROR;
    RETURN[LOOPHOLE[LowHalf[lc], CARDINAL]]};

  ShortenLongPointer: PROC[lp: LONG POINTER] RETURNS[POINTER] = INLINE 
    {local: UNSPECIFIED;
     IF HighHalf[lp] # HighHalf[@local] THEN ERROR;
     RETURN[LOOPHOLE[LowHalf[lp], POINTER]]};

  ShortenLongInteger: PROC[li: LONG INTEGER] RETURNS[INTEGER] = INLINE
    {IF li < FIRST[INTEGER] OR li > LAST[INTEGER] THEN ERROR;
     RETURN[LOOPHOLE[LOOPHOLE[li, Inline.LongNumber].lowbits, INTEGER]]};

END.