Copyright (C) 1994, Digital Equipment Corporation
All rights reserved.
See the file COPYRIGHT for a full description.
Last modified on Mon Jun 20 15:34:10 PDT 1994 by kalsow
UNSAFE MODULE RTPacking;
IMPORT FloatMode, Word;
CONST
Bits = ARRAY [0..3] OF INTEGER { 8, 16, 32, 64 };
VAR
init_done := FALSE;
local : T;
TYPE Inner = RECORD F : BITS 24 FOR CHAR END;
(* STRICTALIGN will require this record to have alignment of 32,
to prevent it's crossing a word boundary if it were to be allocated,
as a field of a containing record, starting at the last or next-to-last
byte of a machine word.
LAZYALIGN will allow alignment of 8 bits.
*)
TYPE Outer
= RECORD
A : CHAR;
B : Inner
(* ^There will be padding before B IFF alignment of Inner is > 8. *)
END;
PROCEDURE IsLazy ( ) : BOOLEAN =
VAR V : Outer;
Offset : CARDINAL;
BEGIN
Offset := ADR ( V . B ) - ADR ( V . A );
RETURN Offset = ADRSIZE ( CHAR )
END IsLazy;
PROCEDURE Local (): T =
VAR
a: RECORD ch: CHAR; x: EXTENDED; END;
b: RECORD ch: CHAR; x: RECORD ch: CHAR; END; END;
i: INTEGER := 1;
x: ADDRESS := ADR (i);
p: UNTRACED REF CHAR := x;
BEGIN
IF NOT init_done THEN
local.word_size := SizeOf (ADRSIZE (INTEGER));
local.long_size := SizeOf (ADRSIZE (LONGINT));
local.max_align := SizeOf (ADR (a.x) - ADR (a.ch));
local.struct_align := SizeOf (ADR (b.x) - ADR (b.ch));
local.little_endian := (p^ = VAL (1, CHAR));
local.float := FloatKind.IEEE;
IF NOT FloatMode.IEEE THEN local.float := FloatKind.VAX; END;
local.lazy_align := IsLazy();
init_done := TRUE;
END;
RETURN local;
END Local;
PROCEDURE SizeOf (n: INTEGER): CARDINAL =
BEGIN
(* convert address units to bits *)
n := n DIV ADRSIZE(CHAR) * BITSIZE(CHAR);
(* look for a known size *)
FOR i := FIRST (Bits) TO LAST (Bits) DO
IF (Bits[i] = n) THEN RETURN n; END;
END;
<*ASSERT FALSE*>
END SizeOf;
PROCEDURE Encode (READONLY t: T): INTEGER =
VAR n := 0;
BEGIN
n := Word.Or (Word.Shift (n, 1), ORD (t.lazy_align));
n := Word.Or (Word.Shift (n, 2), BitSize (t.long_size));
n := Word.Or (Word.Shift (n, 2), BitSize (t.word_size));
n := Word.Or (Word.Shift (n, 2), BitSize (t.max_align));
n := Word.Or (Word.Shift (n, 2), BitSize (t.struct_align));
n := Word.Or (Word.Shift (n, 1), ORD (t.little_endian));
n := Word.Or (Word.Shift (n, 2), ORD (t.float));
RETURN n;
END Encode;
PROCEDURE Decode (i: INTEGER): T =
VAR t: T;
BEGIN
t.float := VAL (Word.And (i, 3), FloatKind); i := Word.Shift (i, -2);
t.little_endian := VAL (Word.And (i, 1), BOOLEAN); i := Word.Shift (i, -1);
t.struct_align := Bits[Word.And (i, 3)]; i := Word.Shift (i, -2);
t.max_align := Bits[Word.And (i, 3)]; i := Word.Shift (i, -2);
t.word_size := Bits[Word.And (i, 3)]; i := Word.Shift (i, -2);
t.long_size := Bits[Word.And (i, 3)]; i := Word.Shift (i, -2);
t.lazy_align := VAL (Word.And (i, 1), BOOLEAN); i := Word.Shift (i, -1);
<*ASSERT i = 0*>
RETURN t;
END Decode;
PROCEDURE BitSize (n: CARDINAL): [FIRST (Bits) .. LAST (Bits)] =
BEGIN
FOR i := FIRST (Bits) TO LAST (Bits) DO
IF (Bits[i] = n) THEN RETURN i; END;
END;
<*ASSERT FALSE*>
END BitSize;
BEGIN
END RTPacking.