]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Make sure not to access past the end of bit-packed arrays
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 29 Oct 2024 12:14:16 +0000 (13:14 +0100)
committerMarc Poulhiès <dkm@gcc.gnu.org>
Tue, 12 Nov 2024 13:05:47 +0000 (14:05 +0100)
The code generated for the routines of the run-time library that implement
support for bit-packed arrays with non-power-of-2 component sizes turns out
to be problematic for the Address Sanitizer and the CHERI architecture, as
it may access past the end of bit-packed arrays in specific cases.

No functional changes.

gcc/ada/ChangeLog:

* s-pack.adb.tmpl: Add '7' suffix to all existing constructs and
add variants with suffixes ranging from '0' to '6'.
(Get_@@): Dereference the address as a record object whose accessed
component is always the last.
(GetU_@@): Likewise.
(Set_@@): Likewise.
(SetU_@@): Likewise.
* libgnat/s-pack03.adb: Regenerate.
* libgnat/s-pack05.adb: Likewise.
* libgnat/s-pack06.adb: Likewise.
* libgnat/s-pack07.adb: Likewise.
* libgnat/s-pack09.adb: Likewise.
* libgnat/s-pack10.adb: Likewise.
* libgnat/s-pack100.adb: Likewise.
* libgnat/s-pack101.adb: Likewise.
* libgnat/s-pack102.adb: Likewise.
* libgnat/s-pack103.adb: Likewise.
* libgnat/s-pack104.adb: Likewise.
* libgnat/s-pack105.adb: Likewise.
* libgnat/s-pack106.adb: Likewise.
* libgnat/s-pack107.adb: Likewise.
* libgnat/s-pack108.adb: Likewise.
* libgnat/s-pack109.adb: Likewise.
* libgnat/s-pack11.adb: Likewise.
* libgnat/s-pack110.adb: Likewise.
* libgnat/s-pack111.adb: Likewise.
* libgnat/s-pack112.adb: Likewise.
* libgnat/s-pack113.adb: Likewise.
* libgnat/s-pack114.adb: Likewise.
* libgnat/s-pack115.adb: Likewise.
* libgnat/s-pack116.adb: Likewise.
* libgnat/s-pack117.adb: Likewise.
* libgnat/s-pack118.adb: Likewise.
* libgnat/s-pack119.adb: Likewise.
* libgnat/s-pack12.adb: Likewise.
* libgnat/s-pack120.adb: Likewise.
* libgnat/s-pack121.adb: Likewise.
* libgnat/s-pack122.adb: Likewise.
* libgnat/s-pack123.adb: Likewise.
* libgnat/s-pack124.adb: Likewise.
* libgnat/s-pack125.adb: Likewise.
* libgnat/s-pack126.adb: Likewise.
* libgnat/s-pack127.adb: Likewise.
* libgnat/s-pack13.adb: Likewise.
* libgnat/s-pack14.adb: Likewise.
* libgnat/s-pack15.adb: Likewise.
* libgnat/s-pack17.adb: Likewise.
* libgnat/s-pack18.adb: Likewise.
* libgnat/s-pack19.adb: Likewise.
* libgnat/s-pack20.adb: Likewise.
* libgnat/s-pack21.adb: Likewise.
* libgnat/s-pack22.adb: Likewise.
* libgnat/s-pack23.adb: Likewise.
* libgnat/s-pack24.adb: Likewise.
* libgnat/s-pack25.adb: Likewise.
* libgnat/s-pack26.adb: Likewise.
* libgnat/s-pack27.adb: Likewise.
* libgnat/s-pack28.adb: Likewise.
* libgnat/s-pack29.adb: Likewise.
* libgnat/s-pack30.adb: Likewise.
* libgnat/s-pack31.adb: Likewise.
* libgnat/s-pack33.adb: Likewise.
* libgnat/s-pack34.adb: Likewise.
* libgnat/s-pack35.adb: Likewise.
* libgnat/s-pack36.adb: Likewise.
* libgnat/s-pack37.adb: Likewise.
* libgnat/s-pack38.adb: Likewise.
* libgnat/s-pack39.adb: Likewise.
* libgnat/s-pack40.adb: Likewise.
* libgnat/s-pack41.adb: Likewise.
* libgnat/s-pack42.adb: Likewise.
* libgnat/s-pack43.adb: Likewise.
* libgnat/s-pack44.adb: Likewise.
* libgnat/s-pack45.adb: Likewise.
* libgnat/s-pack46.adb: Likewise.
* libgnat/s-pack47.adb: Likewise.
* libgnat/s-pack48.adb: Likewise.
* libgnat/s-pack49.adb: Likewise.
* libgnat/s-pack50.adb: Likewise.
* libgnat/s-pack51.adb: Likewise.
* libgnat/s-pack52.adb: Likewise.
* libgnat/s-pack53.adb: Likewise.
* libgnat/s-pack54.adb: Likewise.
* libgnat/s-pack55.adb: Likewise.
* libgnat/s-pack56.adb: Likewise.
* libgnat/s-pack57.adb: Likewise.
* libgnat/s-pack58.adb: Likewise.
* libgnat/s-pack59.adb: Likewise.
* libgnat/s-pack60.adb: Likewise.
* libgnat/s-pack61.adb: Likewise.
* libgnat/s-pack62.adb: Likewise.
* libgnat/s-pack63.adb: Likewise.
* libgnat/s-pack65.adb: Likewise.
* libgnat/s-pack66.adb: Likewise.
* libgnat/s-pack67.adb: Likewise.
* libgnat/s-pack68.adb: Likewise.
* libgnat/s-pack69.adb: Likewise.
* libgnat/s-pack70.adb: Likewise.
* libgnat/s-pack71.adb: Likewise.
* libgnat/s-pack72.adb: Likewise.
* libgnat/s-pack73.adb: Likewise.
* libgnat/s-pack74.adb: Likewise.
* libgnat/s-pack75.adb: Likewise.
* libgnat/s-pack76.adb: Likewise.
* libgnat/s-pack77.adb: Likewise.
* libgnat/s-pack78.adb: Likewise.
* libgnat/s-pack79.adb: Likewise.
* libgnat/s-pack80.adb: Likewise.
* libgnat/s-pack81.adb: Likewise.
* libgnat/s-pack82.adb: Likewise.
* libgnat/s-pack83.adb: Likewise.
* libgnat/s-pack84.adb: Likewise.
* libgnat/s-pack85.adb: Likewise.
* libgnat/s-pack86.adb: Likewise.
* libgnat/s-pack87.adb: Likewise.
* libgnat/s-pack88.adb: Likewise.
* libgnat/s-pack89.adb: Likewise.
* libgnat/s-pack90.adb: Likewise.
* libgnat/s-pack91.adb: Likewise.
* libgnat/s-pack92.adb: Likewise.
* libgnat/s-pack93.adb: Likewise.
* libgnat/s-pack94.adb: Likewise.
* libgnat/s-pack95.adb: Likewise.
* libgnat/s-pack96.adb: Likewise.
* libgnat/s-pack97.adb: Likewise.
* libgnat/s-pack98.adb: Likewise.
* libgnat/s-pack99.adb: Likewise.

121 files changed:
gcc/ada/libgnat/s-pack03.adb
gcc/ada/libgnat/s-pack05.adb
gcc/ada/libgnat/s-pack06.adb
gcc/ada/libgnat/s-pack07.adb
gcc/ada/libgnat/s-pack09.adb
gcc/ada/libgnat/s-pack10.adb
gcc/ada/libgnat/s-pack100.adb
gcc/ada/libgnat/s-pack101.adb
gcc/ada/libgnat/s-pack102.adb
gcc/ada/libgnat/s-pack103.adb
gcc/ada/libgnat/s-pack104.adb
gcc/ada/libgnat/s-pack105.adb
gcc/ada/libgnat/s-pack106.adb
gcc/ada/libgnat/s-pack107.adb
gcc/ada/libgnat/s-pack108.adb
gcc/ada/libgnat/s-pack109.adb
gcc/ada/libgnat/s-pack11.adb
gcc/ada/libgnat/s-pack110.adb
gcc/ada/libgnat/s-pack111.adb
gcc/ada/libgnat/s-pack112.adb
gcc/ada/libgnat/s-pack113.adb
gcc/ada/libgnat/s-pack114.adb
gcc/ada/libgnat/s-pack115.adb
gcc/ada/libgnat/s-pack116.adb
gcc/ada/libgnat/s-pack117.adb
gcc/ada/libgnat/s-pack118.adb
gcc/ada/libgnat/s-pack119.adb
gcc/ada/libgnat/s-pack12.adb
gcc/ada/libgnat/s-pack120.adb
gcc/ada/libgnat/s-pack121.adb
gcc/ada/libgnat/s-pack122.adb
gcc/ada/libgnat/s-pack123.adb
gcc/ada/libgnat/s-pack124.adb
gcc/ada/libgnat/s-pack125.adb
gcc/ada/libgnat/s-pack126.adb
gcc/ada/libgnat/s-pack127.adb
gcc/ada/libgnat/s-pack13.adb
gcc/ada/libgnat/s-pack14.adb
gcc/ada/libgnat/s-pack15.adb
gcc/ada/libgnat/s-pack17.adb
gcc/ada/libgnat/s-pack18.adb
gcc/ada/libgnat/s-pack19.adb
gcc/ada/libgnat/s-pack20.adb
gcc/ada/libgnat/s-pack21.adb
gcc/ada/libgnat/s-pack22.adb
gcc/ada/libgnat/s-pack23.adb
gcc/ada/libgnat/s-pack24.adb
gcc/ada/libgnat/s-pack25.adb
gcc/ada/libgnat/s-pack26.adb
gcc/ada/libgnat/s-pack27.adb
gcc/ada/libgnat/s-pack28.adb
gcc/ada/libgnat/s-pack29.adb
gcc/ada/libgnat/s-pack30.adb
gcc/ada/libgnat/s-pack31.adb
gcc/ada/libgnat/s-pack33.adb
gcc/ada/libgnat/s-pack34.adb
gcc/ada/libgnat/s-pack35.adb
gcc/ada/libgnat/s-pack36.adb
gcc/ada/libgnat/s-pack37.adb
gcc/ada/libgnat/s-pack38.adb
gcc/ada/libgnat/s-pack39.adb
gcc/ada/libgnat/s-pack40.adb
gcc/ada/libgnat/s-pack41.adb
gcc/ada/libgnat/s-pack42.adb
gcc/ada/libgnat/s-pack43.adb
gcc/ada/libgnat/s-pack44.adb
gcc/ada/libgnat/s-pack45.adb
gcc/ada/libgnat/s-pack46.adb
gcc/ada/libgnat/s-pack47.adb
gcc/ada/libgnat/s-pack48.adb
gcc/ada/libgnat/s-pack49.adb
gcc/ada/libgnat/s-pack50.adb
gcc/ada/libgnat/s-pack51.adb
gcc/ada/libgnat/s-pack52.adb
gcc/ada/libgnat/s-pack53.adb
gcc/ada/libgnat/s-pack54.adb
gcc/ada/libgnat/s-pack55.adb
gcc/ada/libgnat/s-pack56.adb
gcc/ada/libgnat/s-pack57.adb
gcc/ada/libgnat/s-pack58.adb
gcc/ada/libgnat/s-pack59.adb
gcc/ada/libgnat/s-pack60.adb
gcc/ada/libgnat/s-pack61.adb
gcc/ada/libgnat/s-pack62.adb
gcc/ada/libgnat/s-pack63.adb
gcc/ada/libgnat/s-pack65.adb
gcc/ada/libgnat/s-pack66.adb
gcc/ada/libgnat/s-pack67.adb
gcc/ada/libgnat/s-pack68.adb
gcc/ada/libgnat/s-pack69.adb
gcc/ada/libgnat/s-pack70.adb
gcc/ada/libgnat/s-pack71.adb
gcc/ada/libgnat/s-pack72.adb
gcc/ada/libgnat/s-pack73.adb
gcc/ada/libgnat/s-pack74.adb
gcc/ada/libgnat/s-pack75.adb
gcc/ada/libgnat/s-pack76.adb
gcc/ada/libgnat/s-pack77.adb
gcc/ada/libgnat/s-pack78.adb
gcc/ada/libgnat/s-pack79.adb
gcc/ada/libgnat/s-pack80.adb
gcc/ada/libgnat/s-pack81.adb
gcc/ada/libgnat/s-pack82.adb
gcc/ada/libgnat/s-pack83.adb
gcc/ada/libgnat/s-pack84.adb
gcc/ada/libgnat/s-pack85.adb
gcc/ada/libgnat/s-pack86.adb
gcc/ada/libgnat/s-pack87.adb
gcc/ada/libgnat/s-pack88.adb
gcc/ada/libgnat/s-pack89.adb
gcc/ada/libgnat/s-pack90.adb
gcc/ada/libgnat/s-pack91.adb
gcc/ada/libgnat/s-pack92.adb
gcc/ada/libgnat/s-pack93.adb
gcc/ada/libgnat/s-pack94.adb
gcc/ada/libgnat/s-pack95.adb
gcc/ada/libgnat/s-pack96.adb
gcc/ada/libgnat/s-pack97.adb
gcc/ada/libgnat/s-pack98.adb
gcc/ada/libgnat/s-pack99.adb
gcc/ada/s-pack.adb.tmpl

index 56b036e91cba170cbb770f9c5c1e68262f3871c8..9df877470845cadaaa8ae21a2a8545c6b3cead58 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_03 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 03 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_03 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_03;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_03;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_03;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_03;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_03;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_03;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_03;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_03;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_03 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_03 --
@@ -90,33 +373,47 @@ package body System.Pack_03 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_03
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_03;
 
@@ -130,32 +427,46 @@ package body System.Pack_03 is
       E       : Bits_03;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_03;
index 0abccaf9c907856d6e8197b40a86061ee8a13d72..39b819a79808c3b95b338a01fbe4ec212c41e0dd 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_05 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 05 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_05 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_05;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_05;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_05;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_05;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_05;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_05;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_05;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_05;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_05 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_05 --
@@ -90,33 +373,47 @@ package body System.Pack_05 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_05
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_05;
 
@@ -130,32 +427,46 @@ package body System.Pack_05 is
       E       : Bits_05;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_05;
index 3b85634190ff193789d2191721ad6adaf55c4607..3fe0b48d5bd733e74fb37e6781b83674568476a2 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_06 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 06 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_06 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_06;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_06 or SetU_06 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_06;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_06 or SetU_06 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_06;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_06 or SetU_06 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_06;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_06 or SetU_06 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_06;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_06 or SetU_06 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_06;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_06 or SetU_06 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_06;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_06 or SetU_06 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_06;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_06 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_06 or SetU_06 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_06 --
@@ -106,33 +501,47 @@ package body System.Pack_06 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_06
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_06;
 
@@ -145,33 +554,47 @@ package body System.Pack_06 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_06
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_06;
 
@@ -185,32 +608,46 @@ package body System.Pack_06 is
       E       : Bits_06;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_06;
@@ -225,32 +662,46 @@ package body System.Pack_06 is
       E       : Bits_06;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_06;
index e93aca55d921eb480ef0ce4eeb34df779d97e118..1f2924c6b4d0a445715a4577c1a2881dcec45c8b 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_07 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 07 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_07 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_07;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_07;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_07;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_07;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_07;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_07;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_07;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_07;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_07 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_07 --
@@ -90,33 +373,47 @@ package body System.Pack_07 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_07
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_07;
 
@@ -130,32 +427,46 @@ package body System.Pack_07 is
       E       : Bits_07;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_07;
index 85bc49acb21e268d99c8a4a4bd586d21a7d57f4a..7c8f78586a6b361421dc69c3de9fab1ae4a02fd8 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_09 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 09 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_09 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_09;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_09;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_09;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_09;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_09;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_09;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_09;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_09;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_09 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_09 --
@@ -90,33 +373,47 @@ package body System.Pack_09 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_09
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_09;
 
@@ -130,32 +427,46 @@ package body System.Pack_09 is
       E       : Bits_09;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_09;
index 6bf3ab76cbb9ee9db5825da334db5f02b24ff85a..fe97ef9d1060ed2260097649bace6ab9fbbb867d 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_10 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 10 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_10 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_10;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_10 or SetU_10 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_10;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_10 or SetU_10 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_10;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_10 or SetU_10 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_10;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_10 or SetU_10 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_10;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_10 or SetU_10 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_10;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_10 or SetU_10 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_10;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_10 or SetU_10 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_10;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_10 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_10 or SetU_10 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_10 --
@@ -106,33 +501,47 @@ package body System.Pack_10 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_10
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_10;
 
@@ -145,33 +554,47 @@ package body System.Pack_10 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_10
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_10;
 
@@ -185,32 +608,46 @@ package body System.Pack_10 is
       E       : Bits_10;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_10;
@@ -225,32 +662,46 @@ package body System.Pack_10 is
       E       : Bits_10;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_10;
index b413f4589332f7989f287ca9c7313dd3ad0d89d2..26889343a499106775f6ab7c0ad0f061f30e4707 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_100 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 100 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_100 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_100;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_100 or SetU_100 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_100;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_100 or SetU_100 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_100;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_100 or SetU_100 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_100;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_100 or SetU_100 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_100;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_100 or SetU_100 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_100;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_100 or SetU_100 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_100;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_100 or SetU_100 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_100;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_100 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_100 or SetU_100 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_100 --
@@ -106,33 +501,47 @@ package body System.Pack_100 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_100
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_100;
 
@@ -145,33 +554,47 @@ package body System.Pack_100 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_100
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_100;
 
@@ -185,32 +608,46 @@ package body System.Pack_100 is
       E       : Bits_100;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_100;
@@ -225,32 +662,46 @@ package body System.Pack_100 is
       E       : Bits_100;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_100;
index 5d5fdb3adee2535a837983088f4c3d99c3a731a1..41a6c1b9b8fbfb8e7d6aa843491d1b78b616dcd2 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_101 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 101 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_101 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_101;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_101;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_101;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_101;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_101;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_101;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_101;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_101;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_101 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_101 --
@@ -90,33 +373,47 @@ package body System.Pack_101 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_101
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_101;
 
@@ -130,32 +427,46 @@ package body System.Pack_101 is
       E       : Bits_101;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_101;
index b00f67bee2e83f7726686dc9c53ca4effbe9d07b..d8f7cadbd57fc6c84e0f46d1c78cf5f90da21d0f 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_102 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 102 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_102 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_102;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_102 or SetU_102 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_102;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_102 or SetU_102 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_102;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_102 or SetU_102 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_102;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_102 or SetU_102 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_102;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_102 or SetU_102 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_102;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_102 or SetU_102 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_102;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_102 or SetU_102 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_102;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_102 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_102 or SetU_102 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_102 --
@@ -106,33 +501,47 @@ package body System.Pack_102 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_102
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_102;
 
@@ -145,33 +554,47 @@ package body System.Pack_102 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_102
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_102;
 
@@ -185,32 +608,46 @@ package body System.Pack_102 is
       E       : Bits_102;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_102;
@@ -225,32 +662,46 @@ package body System.Pack_102 is
       E       : Bits_102;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_102;
index 0839c892d051a9b72cb9f10830bc7da526127d68..e2e108e05a091c34c2a922045532a69bece237f7 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_103 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 103 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_103 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_103;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_103;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_103;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_103;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_103;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_103;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_103;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_103;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_103 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_103 --
@@ -90,33 +373,47 @@ package body System.Pack_103 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_103
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_103;
 
@@ -130,32 +427,46 @@ package body System.Pack_103 is
       E       : Bits_103;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_103;
index b3430e5d214ede8c2056a3c1e03b88d15e48e1a0..42d1c12b7409e3b516a68b41d17257d9dacce54e 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_104 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 104 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_104 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_104;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_104 or SetU_104 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_104;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_104 or SetU_104 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_104;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_104 or SetU_104 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_104;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_104 or SetU_104 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_104;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_104 or SetU_104 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_104;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_104 or SetU_104 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_104;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_104 or SetU_104 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_104;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_104 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_104 or SetU_104 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_104 --
@@ -106,33 +501,47 @@ package body System.Pack_104 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_104
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_104;
 
@@ -145,33 +554,47 @@ package body System.Pack_104 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_104
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_104;
 
@@ -185,32 +608,46 @@ package body System.Pack_104 is
       E       : Bits_104;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_104;
@@ -225,32 +662,46 @@ package body System.Pack_104 is
       E       : Bits_104;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_104;
index 4355aca84fab8025bb1742f5b737ad494c90d4fc..d97441f996b7ca4395fadc6d867019f0e0b0d649 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_105 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 105 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_105 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_105;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_105;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_105;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_105;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_105;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_105;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_105;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_105;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_105 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_105 --
@@ -90,33 +373,47 @@ package body System.Pack_105 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_105
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_105;
 
@@ -130,32 +427,46 @@ package body System.Pack_105 is
       E       : Bits_105;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_105;
index 870ab724811b642d0fd6c43cf5d014a7337cf45a..ccd8b10576c104e74076eccee13b81178b7ea2dd 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_106 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 106 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_106 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_106;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_106 or SetU_106 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_106;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_106 or SetU_106 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_106;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_106 or SetU_106 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_106;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_106 or SetU_106 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_106;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_106 or SetU_106 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_106;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_106 or SetU_106 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_106;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_106 or SetU_106 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_106;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_106 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_106 or SetU_106 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_106 --
@@ -106,33 +501,47 @@ package body System.Pack_106 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_106
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_106;
 
@@ -145,33 +554,47 @@ package body System.Pack_106 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_106
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_106;
 
@@ -185,32 +608,46 @@ package body System.Pack_106 is
       E       : Bits_106;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_106;
@@ -225,32 +662,46 @@ package body System.Pack_106 is
       E       : Bits_106;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_106;
index 22667170b9014143692e3a1e16b531317f28807d..9ac51de8eb2fcdb8953bccc4845eb43f411440c1 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_107 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 107 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_107 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_107;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_107;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_107;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_107;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_107;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_107;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_107;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_107;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_107 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_107 --
@@ -90,33 +373,47 @@ package body System.Pack_107 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_107
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_107;
 
@@ -130,32 +427,46 @@ package body System.Pack_107 is
       E       : Bits_107;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_107;
index 87c8a3372622a579f10a845184a1d4bd878079b5..3c71ff0ceed2a6fc0c14fe8636fa0b600efc1a32 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_108 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 108 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_108 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_108;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_108 or SetU_108 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_108;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_108 or SetU_108 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_108;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_108 or SetU_108 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_108;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_108 or SetU_108 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_108;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_108 or SetU_108 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_108;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_108 or SetU_108 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_108;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_108 or SetU_108 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_108;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_108 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_108 or SetU_108 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_108 --
@@ -106,33 +501,47 @@ package body System.Pack_108 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_108
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_108;
 
@@ -145,33 +554,47 @@ package body System.Pack_108 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_108
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_108;
 
@@ -185,32 +608,46 @@ package body System.Pack_108 is
       E       : Bits_108;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_108;
@@ -225,32 +662,46 @@ package body System.Pack_108 is
       E       : Bits_108;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_108;
index 278d206df3b0f5be0a8627a52eec22d9f18c3ea6..83a696560fb258ade953e9e9853a31a7b2766998 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_109 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 109 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_109 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_109;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_109;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_109;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_109;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_109;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_109;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_109;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_109;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_109 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_109 --
@@ -90,33 +373,47 @@ package body System.Pack_109 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_109
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_109;
 
@@ -130,32 +427,46 @@ package body System.Pack_109 is
       E       : Bits_109;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_109;
index 61312ce41b4afaee7b6334121eef81608cf624c0..5f70095c7ab8e990262571418595517a94bf2c98 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_11 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 11 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_11 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_11;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_11;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_11;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_11;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_11;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_11;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_11;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_11;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_11 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_11 --
@@ -90,33 +373,47 @@ package body System.Pack_11 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_11
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_11;
 
@@ -130,32 +427,46 @@ package body System.Pack_11 is
       E       : Bits_11;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_11;
index 40c588461425c5f4717c10a0e2618115f7258203..9f227888869966d335f0ab139adc7d9c16cc9a40 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_110 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 110 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_110 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_110;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_110 or SetU_110 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_110;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_110 or SetU_110 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_110;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_110 or SetU_110 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_110;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_110 or SetU_110 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_110;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_110 or SetU_110 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_110;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_110 or SetU_110 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_110;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_110 or SetU_110 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_110;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_110 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_110 or SetU_110 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_110 --
@@ -106,33 +501,47 @@ package body System.Pack_110 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_110
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_110;
 
@@ -145,33 +554,47 @@ package body System.Pack_110 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_110
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_110;
 
@@ -185,32 +608,46 @@ package body System.Pack_110 is
       E       : Bits_110;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_110;
@@ -225,32 +662,46 @@ package body System.Pack_110 is
       E       : Bits_110;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_110;
index 4b4e5b40aa7cb6935a4ead2bc6ebbb2e74e6b7e3..71bd24139063f401631f38df47d67794708b8609 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_111 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 111 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_111 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_111;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_111;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_111;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_111;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_111;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_111;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_111;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_111;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_111 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_111 --
@@ -90,33 +373,47 @@ package body System.Pack_111 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_111
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_111;
 
@@ -130,32 +427,46 @@ package body System.Pack_111 is
       E       : Bits_111;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_111;
index 16dedbc833529e2a4baeff17c4af90c05cf932c7..afa75c53f07a7f092f73ae1aedd096abc699578b 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_112 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 112 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_112 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_112;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_112 or SetU_112 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_112;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_112 or SetU_112 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_112;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_112 or SetU_112 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_112;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_112 or SetU_112 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_112;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_112 or SetU_112 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_112;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_112 or SetU_112 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_112;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_112 or SetU_112 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_112;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_112 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_112 or SetU_112 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_112 --
@@ -106,33 +501,47 @@ package body System.Pack_112 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_112
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_112;
 
@@ -145,33 +554,47 @@ package body System.Pack_112 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_112
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_112;
 
@@ -185,32 +608,46 @@ package body System.Pack_112 is
       E       : Bits_112;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_112;
@@ -225,32 +662,46 @@ package body System.Pack_112 is
       E       : Bits_112;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_112;
index 4376c2aac40220b0bb9f39720952411911797a98..cbd2ec8bf9448d1b3f750ddf7c5d9ae5d771b4ed 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_113 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 113 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_113 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_113;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_113;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_113;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_113;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_113;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_113;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_113;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_113;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_113 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_113 --
@@ -90,33 +373,47 @@ package body System.Pack_113 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_113
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_113;
 
@@ -130,32 +427,46 @@ package body System.Pack_113 is
       E       : Bits_113;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_113;
index 7d0d4c6d628bd505c7404a34c393dab9b085f949..3a8f54148e2fc4165a69157a10fe155da6391878 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_114 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 114 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_114 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_114;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_114 or SetU_114 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_114;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_114 or SetU_114 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_114;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_114 or SetU_114 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_114;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_114 or SetU_114 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_114;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_114 or SetU_114 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_114;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_114 or SetU_114 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_114;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_114 or SetU_114 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_114;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_114 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_114 or SetU_114 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_114 --
@@ -106,33 +501,47 @@ package body System.Pack_114 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_114
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_114;
 
@@ -145,33 +554,47 @@ package body System.Pack_114 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_114
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_114;
 
@@ -185,32 +608,46 @@ package body System.Pack_114 is
       E       : Bits_114;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_114;
@@ -225,32 +662,46 @@ package body System.Pack_114 is
       E       : Bits_114;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_114;
index ccca0e730880ba45c6783ee94451901a1cc6cc77..2b4c7dd7af2b513362504d117c0625452fb5881a 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_115 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 115 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_115 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_115;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_115;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_115;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_115;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_115;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_115;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_115;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_115;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_115 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_115 --
@@ -90,33 +373,47 @@ package body System.Pack_115 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_115
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_115;
 
@@ -130,32 +427,46 @@ package body System.Pack_115 is
       E       : Bits_115;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_115;
index 4787e6a48b4c734c7ecfc929eb741f68bbfe11b0..00e83b8624e13cf1e8d45ced45f34d14348415ed 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_116 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 116 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_116 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_116;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_116 or SetU_116 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_116;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_116 or SetU_116 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_116;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_116 or SetU_116 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_116;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_116 or SetU_116 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_116;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_116 or SetU_116 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_116;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_116 or SetU_116 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_116;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_116 or SetU_116 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_116;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_116 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_116 or SetU_116 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_116 --
@@ -106,33 +501,47 @@ package body System.Pack_116 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_116
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_116;
 
@@ -145,33 +554,47 @@ package body System.Pack_116 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_116
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_116;
 
@@ -185,32 +608,46 @@ package body System.Pack_116 is
       E       : Bits_116;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_116;
@@ -225,32 +662,46 @@ package body System.Pack_116 is
       E       : Bits_116;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_116;
index b6940d1fa702d55a657f486f0d62e3c3321d8824..e49a4ecf48af9b704bbb53956b47677413d849bf 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_117 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 117 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_117 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_117;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_117;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_117;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_117;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_117;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_117;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_117;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_117;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_117 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_117 --
@@ -90,33 +373,47 @@ package body System.Pack_117 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_117
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_117;
 
@@ -130,32 +427,46 @@ package body System.Pack_117 is
       E       : Bits_117;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_117;
index 85aa2d5ec78b313adf637b07c94352a63ea4af3b..67dcc0c98598e10e38d65ae3587d76261e0ad6fd 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_118 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 118 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_118 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_118;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_118 or SetU_118 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_118;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_118 or SetU_118 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_118;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_118 or SetU_118 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_118;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_118 or SetU_118 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_118;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_118 or SetU_118 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_118;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_118 or SetU_118 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_118;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_118 or SetU_118 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_118;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_118 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_118 or SetU_118 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_118 --
@@ -106,33 +501,47 @@ package body System.Pack_118 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_118
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_118;
 
@@ -145,33 +554,47 @@ package body System.Pack_118 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_118
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_118;
 
@@ -185,32 +608,46 @@ package body System.Pack_118 is
       E       : Bits_118;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_118;
@@ -225,32 +662,46 @@ package body System.Pack_118 is
       E       : Bits_118;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_118;
index 5351727aab826c869b5f95ca7a62da0b8a9b484b..6351be29a0823d60f2bea7131d96c9e94c5c3cac 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_119 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 119 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_119 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_119;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_119;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_119;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_119;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_119;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_119;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_119;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_119;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_119 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_119 --
@@ -90,33 +373,47 @@ package body System.Pack_119 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_119
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_119;
 
@@ -130,32 +427,46 @@ package body System.Pack_119 is
       E       : Bits_119;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_119;
index 6ff08c2cf62405913d4555227e6e265e27ccec58..3ed31f1fa1a8becd513ef0dcef82513ff8cd4b29 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_12 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 12 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_12 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_12;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_12 or SetU_12 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_12;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_12 or SetU_12 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_12;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_12 or SetU_12 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_12;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_12 or SetU_12 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_12;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_12 or SetU_12 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_12;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_12 or SetU_12 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_12;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_12 or SetU_12 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_12;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_12 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_12 or SetU_12 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_12 --
@@ -106,33 +501,47 @@ package body System.Pack_12 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_12
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_12;
 
@@ -145,33 +554,47 @@ package body System.Pack_12 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_12
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_12;
 
@@ -185,32 +608,46 @@ package body System.Pack_12 is
       E       : Bits_12;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_12;
@@ -225,32 +662,46 @@ package body System.Pack_12 is
       E       : Bits_12;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_12;
index 9ba90991874dff184822d70a086b30cbebb82484..2869e495a07787e4c19dae5241721eb1754c170d 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_120 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 120 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_120 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_120;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_120 or SetU_120 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_120;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_120 or SetU_120 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_120;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_120 or SetU_120 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_120;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_120 or SetU_120 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_120;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_120 or SetU_120 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_120;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_120 or SetU_120 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_120;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_120 or SetU_120 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_120;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_120 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_120 or SetU_120 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_120 --
@@ -106,33 +501,47 @@ package body System.Pack_120 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_120
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_120;
 
@@ -145,33 +554,47 @@ package body System.Pack_120 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_120
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_120;
 
@@ -185,32 +608,46 @@ package body System.Pack_120 is
       E       : Bits_120;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_120;
@@ -225,32 +662,46 @@ package body System.Pack_120 is
       E       : Bits_120;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_120;
index c876c8d1ae4b57524e17ac3cd47b2b1e7d2d2ede..f00afe8e5f2b578d02b93e9c1be75c6bbedcc71e 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_121 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 121 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_121 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_121;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_121;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_121;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_121;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_121;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_121;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_121;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_121;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_121 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_121 --
@@ -90,33 +373,47 @@ package body System.Pack_121 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_121
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_121;
 
@@ -130,32 +427,46 @@ package body System.Pack_121 is
       E       : Bits_121;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_121;
index b118041c36992b97bbb38655703c0e14d29b66c2..9e1bd4ca3601d24e50c521e6b96a71feb8c043b2 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_122 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 122 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_122 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_122;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_122 or SetU_122 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_122;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_122 or SetU_122 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_122;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_122 or SetU_122 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_122;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_122 or SetU_122 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_122;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_122 or SetU_122 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_122;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_122 or SetU_122 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_122;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_122 or SetU_122 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_122;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_122 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_122 or SetU_122 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_122 --
@@ -106,33 +501,47 @@ package body System.Pack_122 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_122
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_122;
 
@@ -145,33 +554,47 @@ package body System.Pack_122 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_122
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_122;
 
@@ -185,32 +608,46 @@ package body System.Pack_122 is
       E       : Bits_122;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_122;
@@ -225,32 +662,46 @@ package body System.Pack_122 is
       E       : Bits_122;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_122;
index db6ee28d450dafb9457261dfa6f70e40f86f9fc5..720f0c4e95db8d9fae088246fc15a585edc7b6d2 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_123 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 123 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_123 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_123;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_123;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_123;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_123;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_123;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_123;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_123;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_123;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_123 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_123 --
@@ -90,33 +373,47 @@ package body System.Pack_123 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_123
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_123;
 
@@ -130,32 +427,46 @@ package body System.Pack_123 is
       E       : Bits_123;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_123;
index 8973af14672ec728a0b1c125d4782bc805d9bb32..5073a6250b608a86f2b2c41272b252469f0678ac 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_124 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 124 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_124 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_124;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_124 or SetU_124 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_124;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_124 or SetU_124 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_124;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_124 or SetU_124 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_124;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_124 or SetU_124 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_124;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_124 or SetU_124 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_124;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_124 or SetU_124 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_124;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_124 or SetU_124 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_124;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_124 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_124 or SetU_124 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_124 --
@@ -106,33 +501,47 @@ package body System.Pack_124 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_124
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_124;
 
@@ -145,33 +554,47 @@ package body System.Pack_124 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_124
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_124;
 
@@ -185,32 +608,46 @@ package body System.Pack_124 is
       E       : Bits_124;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_124;
@@ -225,32 +662,46 @@ package body System.Pack_124 is
       E       : Bits_124;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_124;
index cd5e77e6daeeaebbc7c54164581a682f1098cc4e..9773d33b382814dae5b8071a5b70f187dc6c8fee 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_125 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 125 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_125 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_125;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_125;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_125;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_125;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_125;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_125;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_125;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_125;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_125 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_125 --
@@ -90,33 +373,47 @@ package body System.Pack_125 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_125
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_125;
 
@@ -130,32 +427,46 @@ package body System.Pack_125 is
       E       : Bits_125;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_125;
index 3aa0b24ddda645660f786f2ed26a44033e2741c7..fd38392e6f096cd00b3667b666ef62762158e8d9 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_126 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 126 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_126 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_126;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_126 or SetU_126 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_126;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_126 or SetU_126 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_126;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_126 or SetU_126 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_126;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_126 or SetU_126 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_126;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_126 or SetU_126 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_126;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_126 or SetU_126 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_126;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_126 or SetU_126 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_126;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_126 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_126 or SetU_126 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_126 --
@@ -106,33 +501,47 @@ package body System.Pack_126 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_126
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_126;
 
@@ -145,33 +554,47 @@ package body System.Pack_126 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_126
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_126;
 
@@ -185,32 +608,46 @@ package body System.Pack_126 is
       E       : Bits_126;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_126;
@@ -225,32 +662,46 @@ package body System.Pack_126 is
       E       : Bits_126;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_126;
index f85591e2ff41ca35f1acdbbcd1dcd4ecd5a00c6f..54c6c6ea5679551e2a14562f73f5981c9656c816 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_127 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 127 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_127 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_127;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_127;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_127;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_127;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_127;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_127;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_127;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_127;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_127 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_127 --
@@ -90,33 +373,47 @@ package body System.Pack_127 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_127
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_127;
 
@@ -130,32 +427,46 @@ package body System.Pack_127 is
       E       : Bits_127;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_127;
index 0623f9a314ce9b32ed9266b922dac97a7c90bedd..c867989e8bf4723ca3e8b983dccbba2403d2d2af 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_13 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 13 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_13 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_13;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_13;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_13;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_13;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_13;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_13;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_13;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_13;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_13 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_13 --
@@ -90,33 +373,47 @@ package body System.Pack_13 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_13
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_13;
 
@@ -130,32 +427,46 @@ package body System.Pack_13 is
       E       : Bits_13;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_13;
index c769d976f8de2fa203aa06af6240f9a58d17ec92..71fe2b09259f5db5dfc734e9ff780e0b204f11b6 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_14 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 14 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_14 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_14;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_14 or SetU_14 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_14;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_14 or SetU_14 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_14;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_14 or SetU_14 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_14;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_14 or SetU_14 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_14;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_14 or SetU_14 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_14;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_14 or SetU_14 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_14;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_14 or SetU_14 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_14;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_14 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_14 or SetU_14 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_14 --
@@ -106,33 +501,47 @@ package body System.Pack_14 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_14
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_14;
 
@@ -145,33 +554,47 @@ package body System.Pack_14 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_14
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_14;
 
@@ -185,32 +608,46 @@ package body System.Pack_14 is
       E       : Bits_14;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_14;
@@ -225,32 +662,46 @@ package body System.Pack_14 is
       E       : Bits_14;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_14;
index 70ff0f11723f08aa00d4ef3c1c6a4669e6ef1e4a..13fed1b8818f175b488e799d76a34a969c0d5946 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_15 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 15 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_15 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_15;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_15;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_15;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_15;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_15;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_15;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_15;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_15;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_15 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_15 --
@@ -90,33 +373,47 @@ package body System.Pack_15 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_15
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_15;
 
@@ -130,32 +427,46 @@ package body System.Pack_15 is
       E       : Bits_15;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_15;
index 5347d0adae4e55465d6560f8961bd7ba09cfe188..24c0aeeff0444501b63442d2d6d34b2c8674b4f7 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_17 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 17 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_17 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_17;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_17;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_17;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_17;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_17;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_17;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_17;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_17;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_17 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_17 --
@@ -90,33 +373,47 @@ package body System.Pack_17 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_17
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_17;
 
@@ -130,32 +427,46 @@ package body System.Pack_17 is
       E       : Bits_17;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_17;
index b8a907c1f4bc88e92b885b9fe0d2c969f9cf617c..845497be067c2618e57622a239e6953872583a2e 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_18 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 18 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_18 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_18;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_18 or SetU_18 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_18;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_18 or SetU_18 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_18;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_18 or SetU_18 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_18;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_18 or SetU_18 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_18;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_18 or SetU_18 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_18;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_18 or SetU_18 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_18;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_18 or SetU_18 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_18;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_18 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_18 or SetU_18 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_18 --
@@ -106,33 +501,47 @@ package body System.Pack_18 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_18
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_18;
 
@@ -145,33 +554,47 @@ package body System.Pack_18 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_18
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_18;
 
@@ -185,32 +608,46 @@ package body System.Pack_18 is
       E       : Bits_18;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_18;
@@ -225,32 +662,46 @@ package body System.Pack_18 is
       E       : Bits_18;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_18;
index 5185380326b31f3b59f132b8155095c53470b780..7546624607f9f30218e8432cd6911dab93acd82d 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_19 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 19 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_19 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_19;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_19;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_19;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_19;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_19;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_19;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_19;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_19;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_19 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_19 --
@@ -90,33 +373,47 @@ package body System.Pack_19 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_19
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_19;
 
@@ -130,32 +427,46 @@ package body System.Pack_19 is
       E       : Bits_19;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_19;
index b5e0a6708968346df936068fd3f4f32628f16254..f3db02ea1401557b4c5dad245d14c911928e3687 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_20 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 20 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_20 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_20;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_20 or SetU_20 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_20;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_20 or SetU_20 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_20;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_20 or SetU_20 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_20;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_20 or SetU_20 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_20;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_20 or SetU_20 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_20;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_20 or SetU_20 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_20;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_20 or SetU_20 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_20;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_20 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_20 or SetU_20 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_20 --
@@ -106,33 +501,47 @@ package body System.Pack_20 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_20
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_20;
 
@@ -145,33 +554,47 @@ package body System.Pack_20 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_20
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_20;
 
@@ -185,32 +608,46 @@ package body System.Pack_20 is
       E       : Bits_20;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_20;
@@ -225,32 +662,46 @@ package body System.Pack_20 is
       E       : Bits_20;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_20;
index 8b98af8c1884496b69662ef6d06043fc90a6e349..22845e6628a6b232720d1185e94f7d97fa989598 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_21 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 21 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_21 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_21;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_21;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_21;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_21;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_21;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_21;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_21;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_21;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_21 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_21 --
@@ -90,33 +373,47 @@ package body System.Pack_21 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_21
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_21;
 
@@ -130,32 +427,46 @@ package body System.Pack_21 is
       E       : Bits_21;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_21;
index 14e52268741d5a410310c4f207fb5963967ca760..c5d7042888ac1dedc63d7a119b85ff5aa44a6073 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_22 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 22 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_22 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_22;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_22 or SetU_22 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_22;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_22 or SetU_22 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_22;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_22 or SetU_22 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_22;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_22 or SetU_22 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_22;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_22 or SetU_22 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_22;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_22 or SetU_22 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_22;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_22 or SetU_22 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_22;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_22 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_22 or SetU_22 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_22 --
@@ -106,33 +501,47 @@ package body System.Pack_22 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_22
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_22;
 
@@ -145,33 +554,47 @@ package body System.Pack_22 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_22
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_22;
 
@@ -185,32 +608,46 @@ package body System.Pack_22 is
       E       : Bits_22;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_22;
@@ -225,32 +662,46 @@ package body System.Pack_22 is
       E       : Bits_22;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_22;
index 7284a1b459a3911ae928b2923e141dfa494006e4..ba4dc85a4b2674d4dc0c648e2ffd3847757036c1 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_23 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 23 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_23 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_23;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_23;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_23;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_23;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_23;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_23;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_23;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_23;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_23 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_23 --
@@ -90,33 +373,47 @@ package body System.Pack_23 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_23
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_23;
 
@@ -130,32 +427,46 @@ package body System.Pack_23 is
       E       : Bits_23;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_23;
index b2c2a620fae5d41c6dbc2b0768e037e00b63fff5..f25e3a62f9dbb90f259617a57c10a44495cbec56 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_24 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 24 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_24 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_24;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_24 or SetU_24 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_24;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_24 or SetU_24 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_24;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_24 or SetU_24 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_24;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_24 or SetU_24 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_24;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_24 or SetU_24 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_24;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_24 or SetU_24 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_24;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_24 or SetU_24 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_24;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_24 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_24 or SetU_24 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_24 --
@@ -106,33 +501,47 @@ package body System.Pack_24 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_24
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_24;
 
@@ -145,33 +554,47 @@ package body System.Pack_24 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_24
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_24;
 
@@ -185,32 +608,46 @@ package body System.Pack_24 is
       E       : Bits_24;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_24;
@@ -225,32 +662,46 @@ package body System.Pack_24 is
       E       : Bits_24;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_24;
index dd473d292c98b3af3ffabc7ab25a9ad7d302ff1e..84475fd08ab175f3e045be3d9c81c2cf5f986eef 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_25 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 25 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_25 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_25;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_25;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_25;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_25;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_25;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_25;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_25;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_25;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_25 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_25 --
@@ -90,33 +373,47 @@ package body System.Pack_25 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_25
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_25;
 
@@ -130,32 +427,46 @@ package body System.Pack_25 is
       E       : Bits_25;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_25;
index 4a682b5bb0efbde8718f862413b0b05d6869fdf9..ff35349eac313e80d1ece25a91eb625a253bdd42 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_26 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 26 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_26 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_26;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_26 or SetU_26 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_26;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_26 or SetU_26 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_26;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_26 or SetU_26 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_26;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_26 or SetU_26 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_26;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_26 or SetU_26 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_26;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_26 or SetU_26 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_26;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_26 or SetU_26 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_26;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_26 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_26 or SetU_26 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_26 --
@@ -106,33 +501,47 @@ package body System.Pack_26 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_26
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_26;
 
@@ -145,33 +554,47 @@ package body System.Pack_26 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_26
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_26;
 
@@ -185,32 +608,46 @@ package body System.Pack_26 is
       E       : Bits_26;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_26;
@@ -225,32 +662,46 @@ package body System.Pack_26 is
       E       : Bits_26;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_26;
index c0bc77109cc4eac239ec63a78cb364cac397ea7d..761406c4f147196e21caca1fd617fba75a01a99b 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_27 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 27 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_27 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_27;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_27;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_27;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_27;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_27;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_27;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_27;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_27;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_27 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_27 --
@@ -90,33 +373,47 @@ package body System.Pack_27 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_27
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_27;
 
@@ -130,32 +427,46 @@ package body System.Pack_27 is
       E       : Bits_27;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_27;
index be27c0eee8a15388d4689f228496492a24892be6..5e9f3ef09f3d31bec57002a6f5abc8155a6bbb1c 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_28 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 28 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_28 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_28;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_28 or SetU_28 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_28;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_28 or SetU_28 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_28;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_28 or SetU_28 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_28;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_28 or SetU_28 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_28;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_28 or SetU_28 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_28;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_28 or SetU_28 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_28;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_28 or SetU_28 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_28;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_28 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_28 or SetU_28 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_28 --
@@ -106,33 +501,47 @@ package body System.Pack_28 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_28
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_28;
 
@@ -145,33 +554,47 @@ package body System.Pack_28 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_28
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_28;
 
@@ -185,32 +608,46 @@ package body System.Pack_28 is
       E       : Bits_28;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_28;
@@ -225,32 +662,46 @@ package body System.Pack_28 is
       E       : Bits_28;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_28;
index 2254b908c007b539ad394783540870d1bdf807f0..434c52bbb91581af8a8f27e1969149c811aacc3e 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_29 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 29 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_29 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_29;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_29;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_29;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_29;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_29;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_29;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_29;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_29;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_29 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_29 --
@@ -90,33 +373,47 @@ package body System.Pack_29 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_29
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_29;
 
@@ -130,32 +427,46 @@ package body System.Pack_29 is
       E       : Bits_29;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_29;
index fa48a0a2cfd371de91504ea7781ea33678f9e0a1..14c525b8818945d0ac99d6ba35e0b98a365f8c90 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_30 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 30 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_30 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_30;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_30 or SetU_30 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_30;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_30 or SetU_30 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_30;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_30 or SetU_30 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_30;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_30 or SetU_30 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_30;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_30 or SetU_30 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_30;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_30 or SetU_30 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_30;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_30 or SetU_30 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_30;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_30 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_30 or SetU_30 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_30 --
@@ -106,33 +501,47 @@ package body System.Pack_30 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_30
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_30;
 
@@ -145,33 +554,47 @@ package body System.Pack_30 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_30
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_30;
 
@@ -185,32 +608,46 @@ package body System.Pack_30 is
       E       : Bits_30;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_30;
@@ -225,32 +662,46 @@ package body System.Pack_30 is
       E       : Bits_30;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_30;
index 3234d431efaef8f3e297d7b306c63cd6a0d8c37a..4da512869a2392fd04d196e350abd35695a9b1bb 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_31 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 31 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_31 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_31;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_31;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_31;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_31;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_31;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_31;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_31;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_31;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_31 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_31 --
@@ -90,33 +373,47 @@ package body System.Pack_31 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_31
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_31;
 
@@ -130,32 +427,46 @@ package body System.Pack_31 is
       E       : Bits_31;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_31;
index 4b0aae8f002ea384c296591f6444553f46262adc..ac7004a4e2dc43dd7c4be58b4d0f7a0346d32c1b 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_33 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 33 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_33 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_33;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_33;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_33;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_33;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_33;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_33;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_33;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_33;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_33 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_33 --
@@ -90,33 +373,47 @@ package body System.Pack_33 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_33
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_33;
 
@@ -130,32 +427,46 @@ package body System.Pack_33 is
       E       : Bits_33;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_33;
index 2f8a348ea7c258cb3a44ba29d7ee8f46ab410794..18541c207f3fa1ad3c9fc11779aec7b80b227e14 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_34 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 34 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_34 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_34;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_34 or SetU_34 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_34;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_34 or SetU_34 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_34;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_34 or SetU_34 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_34;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_34 or SetU_34 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_34;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_34 or SetU_34 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_34;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_34 or SetU_34 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_34;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_34 or SetU_34 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_34;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_34 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_34 or SetU_34 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_34 --
@@ -106,33 +501,47 @@ package body System.Pack_34 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_34
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_34;
 
@@ -145,33 +554,47 @@ package body System.Pack_34 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_34
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_34;
 
@@ -185,32 +608,46 @@ package body System.Pack_34 is
       E       : Bits_34;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_34;
@@ -225,32 +662,46 @@ package body System.Pack_34 is
       E       : Bits_34;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_34;
index 82608e1cd092ed9dd57a5c7f6c8a870ae9b3e993..6d02eca0091da94ee26f761ee7bbd360f61132f3 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_35 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 35 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_35 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_35;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_35;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_35;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_35;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_35;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_35;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_35;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_35;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_35 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_35 --
@@ -90,33 +373,47 @@ package body System.Pack_35 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_35
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_35;
 
@@ -130,32 +427,46 @@ package body System.Pack_35 is
       E       : Bits_35;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_35;
index b39556844240da8e1fa523b35a64a1837131a37a..6ce7328208f94008213c5894c698575980c9bea0 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_36 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 36 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_36 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_36;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_36 or SetU_36 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_36;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_36 or SetU_36 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_36;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_36 or SetU_36 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_36;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_36 or SetU_36 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_36;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_36 or SetU_36 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_36;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_36 or SetU_36 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_36;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_36 or SetU_36 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_36;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_36 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_36 or SetU_36 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_36 --
@@ -106,33 +501,47 @@ package body System.Pack_36 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_36
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_36;
 
@@ -145,33 +554,47 @@ package body System.Pack_36 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_36
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_36;
 
@@ -185,32 +608,46 @@ package body System.Pack_36 is
       E       : Bits_36;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_36;
@@ -225,32 +662,46 @@ package body System.Pack_36 is
       E       : Bits_36;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_36;
index 0f46635120b109adb60fac6f21eda2703214a0e1..373fe8d30ef44698b16ee5b3ed32d3166ce46e88 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_37 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 37 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_37 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_37;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_37;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_37;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_37;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_37;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_37;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_37;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_37;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_37 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_37 --
@@ -90,33 +373,47 @@ package body System.Pack_37 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_37
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_37;
 
@@ -130,32 +427,46 @@ package body System.Pack_37 is
       E       : Bits_37;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_37;
index 97303c9aea01b7e31d7bb8cc26dd30b314b5d33c..dcaaa4e7a8f81e372690e3021930bba55fe676b5 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_38 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 38 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_38 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_38;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_38 or SetU_38 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_38;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_38 or SetU_38 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_38;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_38 or SetU_38 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_38;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_38 or SetU_38 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_38;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_38 or SetU_38 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_38;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_38 or SetU_38 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_38;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_38 or SetU_38 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_38;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_38 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_38 or SetU_38 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_38 --
@@ -106,33 +501,47 @@ package body System.Pack_38 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_38
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_38;
 
@@ -145,33 +554,47 @@ package body System.Pack_38 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_38
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_38;
 
@@ -185,32 +608,46 @@ package body System.Pack_38 is
       E       : Bits_38;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_38;
@@ -225,32 +662,46 @@ package body System.Pack_38 is
       E       : Bits_38;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_38;
index e712ba0b8db8ba80d691bdd0dd8061365a7e3a0c..881370541c06c7ec8a680941cdf225357348528a 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_39 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 39 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_39 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_39;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_39;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_39;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_39;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_39;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_39;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_39;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_39;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_39 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_39 --
@@ -90,33 +373,47 @@ package body System.Pack_39 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_39
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_39;
 
@@ -130,32 +427,46 @@ package body System.Pack_39 is
       E       : Bits_39;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_39;
index 44d8aa49a32c03a357d527c5e4ce90d7f9ff9e3e..deac9336b2661e9f6b40b53f4f023597dd3e945d 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_40 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 40 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_40 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_40;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_40 or SetU_40 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_40;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_40 or SetU_40 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_40;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_40 or SetU_40 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_40;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_40 or SetU_40 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_40;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_40 or SetU_40 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_40;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_40 or SetU_40 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_40;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_40 or SetU_40 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_40;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_40 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_40 or SetU_40 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_40 --
@@ -106,33 +501,47 @@ package body System.Pack_40 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_40
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_40;
 
@@ -145,33 +554,47 @@ package body System.Pack_40 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_40
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_40;
 
@@ -185,32 +608,46 @@ package body System.Pack_40 is
       E       : Bits_40;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_40;
@@ -225,32 +662,46 @@ package body System.Pack_40 is
       E       : Bits_40;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_40;
index cb7378a693c9264c66e8a7b1dca1935ed20aff44..782fa41ff9e1efc86cc7813a5a79b465f0cb8c2b 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_41 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 41 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_41 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_41;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_41;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_41;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_41;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_41;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_41;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_41;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_41;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_41 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_41 --
@@ -90,33 +373,47 @@ package body System.Pack_41 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_41
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_41;
 
@@ -130,32 +427,46 @@ package body System.Pack_41 is
       E       : Bits_41;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_41;
index 96b388152911685e82ccbd63c00b151c08623fa9..a2a7ce03400e52992b76a63ca2db1fcd6b9fb98e 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_42 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 42 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_42 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_42;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_42 or SetU_42 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_42;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_42 or SetU_42 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_42;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_42 or SetU_42 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_42;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_42 or SetU_42 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_42;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_42 or SetU_42 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_42;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_42 or SetU_42 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_42;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_42 or SetU_42 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_42;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_42 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_42 or SetU_42 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_42 --
@@ -106,33 +501,47 @@ package body System.Pack_42 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_42
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_42;
 
@@ -145,33 +554,47 @@ package body System.Pack_42 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_42
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_42;
 
@@ -185,32 +608,46 @@ package body System.Pack_42 is
       E       : Bits_42;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_42;
@@ -225,32 +662,46 @@ package body System.Pack_42 is
       E       : Bits_42;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_42;
index eb59a37fc38ac996dbeda53b25f196cf78be2d19..7dffd40aa23335a8731111979f1416bbe12ccb6b 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_43 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 43 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_43 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_43;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_43;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_43;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_43;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_43;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_43;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_43;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_43;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_43 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_43 --
@@ -90,33 +373,47 @@ package body System.Pack_43 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_43
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_43;
 
@@ -130,32 +427,46 @@ package body System.Pack_43 is
       E       : Bits_43;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_43;
index f11db4442338ed7a16a832a0da6cd765eced7f84..29c492036d3b2e5acdd3f733fed4b8cf16acb15b 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_44 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 44 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_44 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_44;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_44 or SetU_44 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_44;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_44 or SetU_44 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_44;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_44 or SetU_44 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_44;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_44 or SetU_44 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_44;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_44 or SetU_44 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_44;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_44 or SetU_44 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_44;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_44 or SetU_44 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_44;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_44 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_44 or SetU_44 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_44 --
@@ -106,33 +501,47 @@ package body System.Pack_44 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_44
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_44;
 
@@ -145,33 +554,47 @@ package body System.Pack_44 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_44
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_44;
 
@@ -185,32 +608,46 @@ package body System.Pack_44 is
       E       : Bits_44;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_44;
@@ -225,32 +662,46 @@ package body System.Pack_44 is
       E       : Bits_44;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_44;
index a880615389e2f1eab07c5894b13d01841a3e4411..4cce386090be6d9117c9e2de39423b2def889f12 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_45 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 45 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_45 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_45;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_45;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_45;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_45;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_45;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_45;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_45;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_45;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_45 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_45 --
@@ -90,33 +373,47 @@ package body System.Pack_45 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_45
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_45;
 
@@ -130,32 +427,46 @@ package body System.Pack_45 is
       E       : Bits_45;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_45;
index 586e97a5ff326c6d8530272652c081072d52a3b8..0ba0631334f4fdcaa858ebdd2e7d773de85e6795 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_46 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 46 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_46 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_46;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_46 or SetU_46 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_46;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_46 or SetU_46 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_46;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_46 or SetU_46 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_46;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_46 or SetU_46 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_46;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_46 or SetU_46 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_46;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_46 or SetU_46 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_46;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_46 or SetU_46 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_46;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_46 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_46 or SetU_46 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_46 --
@@ -106,33 +501,47 @@ package body System.Pack_46 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_46
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_46;
 
@@ -145,33 +554,47 @@ package body System.Pack_46 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_46
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_46;
 
@@ -185,32 +608,46 @@ package body System.Pack_46 is
       E       : Bits_46;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_46;
@@ -225,32 +662,46 @@ package body System.Pack_46 is
       E       : Bits_46;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_46;
index d315c817973647d9991aed903f6db75dff71402e..efd1e1edf32b85f1e1563f6aa4ba0e68daefeef2 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_47 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 47 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_47 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_47;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_47;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_47;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_47;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_47;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_47;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_47;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_47;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_47 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_47 --
@@ -90,33 +373,47 @@ package body System.Pack_47 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_47
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_47;
 
@@ -130,32 +427,46 @@ package body System.Pack_47 is
       E       : Bits_47;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_47;
index 247af835cf0418ce08d514f086d39862c0a91eb4..a94c5fe8f0c1a7473d512785733888de8f289a2c 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_48 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 48 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_48 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_48;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_48 or SetU_48 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_48;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_48 or SetU_48 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_48;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_48 or SetU_48 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_48;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_48 or SetU_48 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_48;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_48 or SetU_48 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_48;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_48 or SetU_48 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_48;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_48 or SetU_48 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_48;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_48 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_48 or SetU_48 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_48 --
@@ -106,33 +501,47 @@ package body System.Pack_48 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_48
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_48;
 
@@ -145,33 +554,47 @@ package body System.Pack_48 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_48
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_48;
 
@@ -185,32 +608,46 @@ package body System.Pack_48 is
       E       : Bits_48;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_48;
@@ -225,32 +662,46 @@ package body System.Pack_48 is
       E       : Bits_48;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_48;
index a054313f4815dd0a425b69a19b841195283bb59c..5c8df0ce192e374f159d381db20681d23da94144 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_49 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 49 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_49 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_49;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_49;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_49;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_49;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_49;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_49;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_49;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_49;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_49 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_49 --
@@ -90,33 +373,47 @@ package body System.Pack_49 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_49
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_49;
 
@@ -130,32 +427,46 @@ package body System.Pack_49 is
       E       : Bits_49;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_49;
index c03c0cf2053bc36bf08ce25946fa0484f7ae3a88..769fe807176fffb677b32d5e541c36752f72fbf6 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_50 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 50 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_50 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_50;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_50 or SetU_50 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_50;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_50 or SetU_50 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_50;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_50 or SetU_50 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_50;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_50 or SetU_50 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_50;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_50 or SetU_50 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_50;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_50 or SetU_50 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_50;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_50 or SetU_50 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_50;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_50 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_50 or SetU_50 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_50 --
@@ -106,33 +501,47 @@ package body System.Pack_50 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_50
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_50;
 
@@ -145,33 +554,47 @@ package body System.Pack_50 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_50
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_50;
 
@@ -185,32 +608,46 @@ package body System.Pack_50 is
       E       : Bits_50;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_50;
@@ -225,32 +662,46 @@ package body System.Pack_50 is
       E       : Bits_50;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_50;
index 46abe28e6dad7979561becbbc4ab3d80a4ce6820..89fb838b154139c5ae0e564ba96275b040e15841 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_51 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 51 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_51 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_51;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_51;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_51;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_51;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_51;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_51;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_51;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_51;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_51 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_51 --
@@ -90,33 +373,47 @@ package body System.Pack_51 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_51
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_51;
 
@@ -130,32 +427,46 @@ package body System.Pack_51 is
       E       : Bits_51;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_51;
index 6cae3f78112b8d9a1e47354e67d510a5e024376b..d9bcf57611c0225abcff705e6c421cd588795d98 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_52 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 52 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_52 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_52;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_52 or SetU_52 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_52;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_52 or SetU_52 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_52;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_52 or SetU_52 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_52;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_52 or SetU_52 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_52;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_52 or SetU_52 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_52;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_52 or SetU_52 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_52;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_52 or SetU_52 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_52;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_52 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_52 or SetU_52 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_52 --
@@ -106,33 +501,47 @@ package body System.Pack_52 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_52
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_52;
 
@@ -145,33 +554,47 @@ package body System.Pack_52 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_52
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_52;
 
@@ -185,32 +608,46 @@ package body System.Pack_52 is
       E       : Bits_52;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_52;
@@ -225,32 +662,46 @@ package body System.Pack_52 is
       E       : Bits_52;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_52;
index 6a51fa6b2e7c7707a310302a7f697c7a9ffc0059..58d3e7a4d492993d1fcee17325cb91236adb4d50 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_53 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 53 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_53 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_53;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_53;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_53;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_53;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_53;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_53;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_53;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_53;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_53 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_53 --
@@ -90,33 +373,47 @@ package body System.Pack_53 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_53
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_53;
 
@@ -130,32 +427,46 @@ package body System.Pack_53 is
       E       : Bits_53;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_53;
index 2cc4e9cfb8809a0825afe292f1af3f9f89094bc3..eedc0578f8fc9f1f9925c6a967a2c55041cb83ea 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_54 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 54 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_54 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_54;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_54 or SetU_54 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_54;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_54 or SetU_54 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_54;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_54 or SetU_54 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_54;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_54 or SetU_54 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_54;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_54 or SetU_54 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_54;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_54 or SetU_54 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_54;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_54 or SetU_54 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_54;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_54 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_54 or SetU_54 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_54 --
@@ -106,33 +501,47 @@ package body System.Pack_54 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_54
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_54;
 
@@ -145,33 +554,47 @@ package body System.Pack_54 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_54
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_54;
 
@@ -185,32 +608,46 @@ package body System.Pack_54 is
       E       : Bits_54;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_54;
@@ -225,32 +662,46 @@ package body System.Pack_54 is
       E       : Bits_54;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_54;
index b1264c74b4d67a352e4cc6b9b1e2954915bec0a6..fafe9548331cb0b8066feaa04270c2a2b0e4763f 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_55 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 55 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_55 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_55;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_55;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_55;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_55;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_55;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_55;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_55;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_55;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_55 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_55 --
@@ -90,33 +373,47 @@ package body System.Pack_55 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_55
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_55;
 
@@ -130,32 +427,46 @@ package body System.Pack_55 is
       E       : Bits_55;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_55;
index 100b34895a0a2a0365ea149a3ad9d27e957b6716..c788d4748c3bcd21397d54441f998722443b3449 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_56 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 56 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_56 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_56;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_56 or SetU_56 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_56;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_56 or SetU_56 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_56;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_56 or SetU_56 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_56;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_56 or SetU_56 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_56;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_56 or SetU_56 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_56;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_56 or SetU_56 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_56;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_56 or SetU_56 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_56;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_56 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_56 or SetU_56 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_56 --
@@ -106,33 +501,47 @@ package body System.Pack_56 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_56
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_56;
 
@@ -145,33 +554,47 @@ package body System.Pack_56 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_56
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_56;
 
@@ -185,32 +608,46 @@ package body System.Pack_56 is
       E       : Bits_56;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_56;
@@ -225,32 +662,46 @@ package body System.Pack_56 is
       E       : Bits_56;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_56;
index 1056212b8d291f842249f8562220aaaccc511a44..70b22acb5d66b3a9e3a8d00378303348790d774e 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_57 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 57 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_57 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_57;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_57;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_57;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_57;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_57;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_57;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_57;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_57;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_57 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_57 --
@@ -90,33 +373,47 @@ package body System.Pack_57 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_57
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_57;
 
@@ -130,32 +427,46 @@ package body System.Pack_57 is
       E       : Bits_57;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_57;
index c429d38d3b489fdc79a854b101e1ed965de4202f..244c1638bbd837d23e8670e471866729833605c7 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_58 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 58 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_58 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_58;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_58 or SetU_58 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_58;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_58 or SetU_58 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_58;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_58 or SetU_58 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_58;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_58 or SetU_58 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_58;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_58 or SetU_58 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_58;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_58 or SetU_58 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_58;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_58 or SetU_58 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_58;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_58 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_58 or SetU_58 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_58 --
@@ -106,33 +501,47 @@ package body System.Pack_58 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_58
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_58;
 
@@ -145,33 +554,47 @@ package body System.Pack_58 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_58
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_58;
 
@@ -185,32 +608,46 @@ package body System.Pack_58 is
       E       : Bits_58;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_58;
@@ -225,32 +662,46 @@ package body System.Pack_58 is
       E       : Bits_58;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_58;
index fe304b96d377c7ce11e99649ab369664978d8105..c44931fa658b8ceb2376cfb4c847d349d6b69bff 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_59 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 59 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_59 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_59;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_59;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_59;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_59;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_59;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_59;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_59;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_59;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_59 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_59 --
@@ -90,33 +373,47 @@ package body System.Pack_59 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_59
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_59;
 
@@ -130,32 +427,46 @@ package body System.Pack_59 is
       E       : Bits_59;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_59;
index 1d1422b7bcd73e03ce72f360421198663227a449..4be8ff86b408be75acaa9ad956b52720b3046ee4 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_60 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 60 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_60 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_60;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_60 or SetU_60 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_60;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_60 or SetU_60 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_60;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_60 or SetU_60 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_60;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_60 or SetU_60 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_60;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_60 or SetU_60 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_60;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_60 or SetU_60 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_60;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_60 or SetU_60 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_60;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_60 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_60 or SetU_60 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_60 --
@@ -106,33 +501,47 @@ package body System.Pack_60 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_60
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_60;
 
@@ -145,33 +554,47 @@ package body System.Pack_60 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_60
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_60;
 
@@ -185,32 +608,46 @@ package body System.Pack_60 is
       E       : Bits_60;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_60;
@@ -225,32 +662,46 @@ package body System.Pack_60 is
       E       : Bits_60;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_60;
index d744ff34b9bc70ed9b70eee2c87d195a0360d3b7..dd81dae5ac70a648d746fa41e48de516d6e8fc67 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_61 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 61 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_61 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_61;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_61;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_61;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_61;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_61;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_61;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_61;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_61;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_61 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_61 --
@@ -90,33 +373,47 @@ package body System.Pack_61 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_61
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_61;
 
@@ -130,32 +427,46 @@ package body System.Pack_61 is
       E       : Bits_61;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_61;
index d4745cfa2828c4604128e1aa54622b5d1eea7ee7..00e846de7b583ab135e18cab1e860710d675e999 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_62 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 62 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_62 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_62;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_62 or SetU_62 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_62;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_62 or SetU_62 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_62;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_62 or SetU_62 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_62;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_62 or SetU_62 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_62;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_62 or SetU_62 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_62;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_62 or SetU_62 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_62;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_62 or SetU_62 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_62;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_62 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_62 or SetU_62 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_62 --
@@ -106,33 +501,47 @@ package body System.Pack_62 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_62
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_62;
 
@@ -145,33 +554,47 @@ package body System.Pack_62 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_62
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_62;
 
@@ -185,32 +608,46 @@ package body System.Pack_62 is
       E       : Bits_62;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_62;
@@ -225,32 +662,46 @@ package body System.Pack_62 is
       E       : Bits_62;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_62;
index 257fbabb33c31f16cf718297222bd34be5092b2e..ddaa42d3b65735dfb1d41b2a70dd4b3ff9e1c044 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_63 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 63 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_63 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_63;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_63;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_63;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_63;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_63;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_63;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_63;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_63;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_63 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_63 --
@@ -90,33 +373,47 @@ package body System.Pack_63 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_63
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_63;
 
@@ -130,32 +427,46 @@ package body System.Pack_63 is
       E       : Bits_63;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_63;
index 205b911a5ca9b1edae9c13a943a9921789d196a2..1f253ddc6255bf3f0de7f940b3471fbc32a53772 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_65 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 65 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_65 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_65;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_65;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_65;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_65;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_65;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_65;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_65;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_65;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_65 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_65 --
@@ -90,33 +373,47 @@ package body System.Pack_65 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_65
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_65;
 
@@ -130,32 +427,46 @@ package body System.Pack_65 is
       E       : Bits_65;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_65;
index cb95338d85841f6d9a53c7e194118fd037436a88..ba074510aa1cf9de4d3b2f89e2447d212d1aae79 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_66 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 66 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_66 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_66;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_66 or SetU_66 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_66;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_66 or SetU_66 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_66;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_66 or SetU_66 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_66;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_66 or SetU_66 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_66;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_66 or SetU_66 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_66;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_66 or SetU_66 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_66;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_66 or SetU_66 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_66;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_66 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_66 or SetU_66 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_66 --
@@ -106,33 +501,47 @@ package body System.Pack_66 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_66
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_66;
 
@@ -145,33 +554,47 @@ package body System.Pack_66 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_66
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_66;
 
@@ -185,32 +608,46 @@ package body System.Pack_66 is
       E       : Bits_66;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_66;
@@ -225,32 +662,46 @@ package body System.Pack_66 is
       E       : Bits_66;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_66;
index 194510a1e32e34e7d91dfd48e54280072bc8d6a1..7d09a4373cf0eb0004a447d899ee56c35e0e0393 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_67 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 67 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_67 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_67;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_67;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_67;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_67;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_67;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_67;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_67;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_67;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_67 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_67 --
@@ -90,33 +373,47 @@ package body System.Pack_67 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_67
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_67;
 
@@ -130,32 +427,46 @@ package body System.Pack_67 is
       E       : Bits_67;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_67;
index cf7043dcc0b9d3bb3508a214c5472fdcd3bcc3fa..d27490577d49385cc23cf586b415b0f2f0ef6be7 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_68 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 68 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_68 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_68;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_68 or SetU_68 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_68;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_68 or SetU_68 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_68;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_68 or SetU_68 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_68;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_68 or SetU_68 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_68;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_68 or SetU_68 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_68;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_68 or SetU_68 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_68;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_68 or SetU_68 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_68;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_68 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_68 or SetU_68 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_68 --
@@ -106,33 +501,47 @@ package body System.Pack_68 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_68
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_68;
 
@@ -145,33 +554,47 @@ package body System.Pack_68 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_68
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_68;
 
@@ -185,32 +608,46 @@ package body System.Pack_68 is
       E       : Bits_68;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_68;
@@ -225,32 +662,46 @@ package body System.Pack_68 is
       E       : Bits_68;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_68;
index 670e6129d86cf5d74a7a2a911e993d702d9aaed2..e1058308ff0e6f4e685d1180b67fe43707a2025a 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_69 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 69 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_69 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_69;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_69;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_69;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_69;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_69;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_69;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_69;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_69;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_69 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_69 --
@@ -90,33 +373,47 @@ package body System.Pack_69 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_69
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_69;
 
@@ -130,32 +427,46 @@ package body System.Pack_69 is
       E       : Bits_69;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_69;
index aa320f67ae11dc8cf95c2f333a2ba939b780c552..39fa6dd76b9bc2680ec8b30e1ecc5bac981751da 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_70 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 70 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_70 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_70;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_70 or SetU_70 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_70;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_70 or SetU_70 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_70;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_70 or SetU_70 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_70;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_70 or SetU_70 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_70;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_70 or SetU_70 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_70;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_70 or SetU_70 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_70;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_70 or SetU_70 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_70;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_70 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_70 or SetU_70 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_70 --
@@ -106,33 +501,47 @@ package body System.Pack_70 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_70
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_70;
 
@@ -145,33 +554,47 @@ package body System.Pack_70 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_70
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_70;
 
@@ -185,32 +608,46 @@ package body System.Pack_70 is
       E       : Bits_70;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_70;
@@ -225,32 +662,46 @@ package body System.Pack_70 is
       E       : Bits_70;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_70;
index 748a1c6b3818c5b010096342cd98460b2734c0cb..232a8ded4d27335b2c3e6188458cd74cab4902dd 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_71 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 71 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_71 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_71;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_71;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_71;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_71;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_71;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_71;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_71;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_71;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_71 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_71 --
@@ -90,33 +373,47 @@ package body System.Pack_71 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_71
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_71;
 
@@ -130,32 +427,46 @@ package body System.Pack_71 is
       E       : Bits_71;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_71;
index b2c463a04e638e5cd88c01947cb15b25cc6caa39..439f5ba579eae68587eaec6c72aee5d608f26939 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_72 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 72 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_72 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_72;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_72 or SetU_72 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_72;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_72 or SetU_72 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_72;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_72 or SetU_72 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_72;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_72 or SetU_72 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_72;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_72 or SetU_72 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_72;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_72 or SetU_72 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_72;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_72 or SetU_72 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_72;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_72 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_72 or SetU_72 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_72 --
@@ -106,33 +501,47 @@ package body System.Pack_72 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_72
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_72;
 
@@ -145,33 +554,47 @@ package body System.Pack_72 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_72
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_72;
 
@@ -185,32 +608,46 @@ package body System.Pack_72 is
       E       : Bits_72;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_72;
@@ -225,32 +662,46 @@ package body System.Pack_72 is
       E       : Bits_72;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_72;
index 3abaebe480852f2a4aa739a0c0723908174be0a0..ddca1ead799e91c361c977d54d7f9eee23287561 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_73 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 73 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_73 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_73;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_73;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_73;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_73;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_73;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_73;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_73;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_73;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_73 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_73 --
@@ -90,33 +373,47 @@ package body System.Pack_73 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_73
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_73;
 
@@ -130,32 +427,46 @@ package body System.Pack_73 is
       E       : Bits_73;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_73;
index 2fe64bc89578dbee6922b35e950c653683a470e7..e157428d3ecff47185f5d10e7d7ca34e66901c31 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_74 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 74 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_74 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_74;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_74 or SetU_74 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_74;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_74 or SetU_74 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_74;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_74 or SetU_74 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_74;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_74 or SetU_74 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_74;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_74 or SetU_74 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_74;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_74 or SetU_74 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_74;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_74 or SetU_74 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_74;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_74 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_74 or SetU_74 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_74 --
@@ -106,33 +501,47 @@ package body System.Pack_74 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_74
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_74;
 
@@ -145,33 +554,47 @@ package body System.Pack_74 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_74
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_74;
 
@@ -185,32 +608,46 @@ package body System.Pack_74 is
       E       : Bits_74;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_74;
@@ -225,32 +662,46 @@ package body System.Pack_74 is
       E       : Bits_74;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_74;
index d62afc9dec6767b23b585b6bb36be72a615b3e54..45219c96127410a0989b57c71ec40ea3dda60a35 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_75 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 75 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_75 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_75;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_75;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_75;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_75;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_75;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_75;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_75;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_75;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_75 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_75 --
@@ -90,33 +373,47 @@ package body System.Pack_75 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_75
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_75;
 
@@ -130,32 +427,46 @@ package body System.Pack_75 is
       E       : Bits_75;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_75;
index 30c15964f47f7da65df2b58e7d6f83b15ec03733..86ce803191bc82022e3d26b88448d5a77f4e4c42 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_76 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 76 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_76 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_76;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_76 or SetU_76 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_76;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_76 or SetU_76 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_76;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_76 or SetU_76 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_76;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_76 or SetU_76 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_76;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_76 or SetU_76 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_76;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_76 or SetU_76 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_76;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_76 or SetU_76 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_76;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_76 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_76 or SetU_76 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_76 --
@@ -106,33 +501,47 @@ package body System.Pack_76 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_76
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_76;
 
@@ -145,33 +554,47 @@ package body System.Pack_76 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_76
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_76;
 
@@ -185,32 +608,46 @@ package body System.Pack_76 is
       E       : Bits_76;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_76;
@@ -225,32 +662,46 @@ package body System.Pack_76 is
       E       : Bits_76;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_76;
index eadc77987ba5d59c786d6f178271d7f4e8d221f4..f4bb31bb715bb963c1b0f7faec0ff4ee52724b9f 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_77 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 77 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_77 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_77;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_77;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_77;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_77;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_77;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_77;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_77;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_77;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_77 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_77 --
@@ -90,33 +373,47 @@ package body System.Pack_77 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_77
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_77;
 
@@ -130,32 +427,46 @@ package body System.Pack_77 is
       E       : Bits_77;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_77;
index e5f1896f245b3b9984f8cc4364d3a2cc3ba88d78..0b87996c1ab3d06817da4110e500d498d4486b68 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_78 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 78 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_78 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_78;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_78 or SetU_78 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_78;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_78 or SetU_78 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_78;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_78 or SetU_78 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_78;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_78 or SetU_78 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_78;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_78 or SetU_78 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_78;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_78 or SetU_78 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_78;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_78 or SetU_78 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_78;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_78 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_78 or SetU_78 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_78 --
@@ -106,33 +501,47 @@ package body System.Pack_78 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_78
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_78;
 
@@ -145,33 +554,47 @@ package body System.Pack_78 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_78
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_78;
 
@@ -185,32 +608,46 @@ package body System.Pack_78 is
       E       : Bits_78;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_78;
@@ -225,32 +662,46 @@ package body System.Pack_78 is
       E       : Bits_78;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_78;
index f2e52afd8cc5d7b1b569c5806cccaf76bd09627a..bcf854f1385408bd91c8638c1eacd49d3ec2a12f 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_79 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 79 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_79 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_79;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_79;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_79;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_79;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_79;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_79;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_79;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_79;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_79 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_79 --
@@ -90,33 +373,47 @@ package body System.Pack_79 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_79
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_79;
 
@@ -130,32 +427,46 @@ package body System.Pack_79 is
       E       : Bits_79;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_79;
index 8668ad0200be1c2ac579f3fc2c2468b727d94321..5769fe7e95054d873d8ab1b5d57ac8ff2e0830f3 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_80 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 80 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_80 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_80;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_80 or SetU_80 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_80;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_80 or SetU_80 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_80;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_80 or SetU_80 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_80;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_80 or SetU_80 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_80;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_80 or SetU_80 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_80;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_80 or SetU_80 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_80;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_80 or SetU_80 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_80;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_80 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_80 or SetU_80 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_80 --
@@ -106,33 +501,47 @@ package body System.Pack_80 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_80
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_80;
 
@@ -145,33 +554,47 @@ package body System.Pack_80 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_80
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_80;
 
@@ -185,32 +608,46 @@ package body System.Pack_80 is
       E       : Bits_80;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_80;
@@ -225,32 +662,46 @@ package body System.Pack_80 is
       E       : Bits_80;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_80;
index 2100734567613e8d09fe50bea42b6db03f05ba95..199a5173bf6c7f4c878eb6824b2e3af9ed051179 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_81 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 81 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_81 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_81;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_81;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_81;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_81;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_81;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_81;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_81;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_81;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_81 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_81 --
@@ -90,33 +373,47 @@ package body System.Pack_81 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_81
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_81;
 
@@ -130,32 +427,46 @@ package body System.Pack_81 is
       E       : Bits_81;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_81;
index 9e405a0cc2e85b9b8a0ff261cc124f1f846edb8e..904bf6c3c08520ce643865825aa2fb5e9d505147 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_82 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 82 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_82 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_82;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_82 or SetU_82 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_82;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_82 or SetU_82 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_82;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_82 or SetU_82 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_82;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_82 or SetU_82 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_82;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_82 or SetU_82 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_82;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_82 or SetU_82 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_82;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_82 or SetU_82 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_82;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_82 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_82 or SetU_82 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_82 --
@@ -106,33 +501,47 @@ package body System.Pack_82 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_82
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_82;
 
@@ -145,33 +554,47 @@ package body System.Pack_82 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_82
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_82;
 
@@ -185,32 +608,46 @@ package body System.Pack_82 is
       E       : Bits_82;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_82;
@@ -225,32 +662,46 @@ package body System.Pack_82 is
       E       : Bits_82;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_82;
index 49420e6c0f769f4af7c9d2ed407249459d5e2e65..8c3729049e7784e46bd9340572c44a7aaf0a2271 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_83 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 83 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_83 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_83;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_83;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_83;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_83;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_83;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_83;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_83;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_83;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_83 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_83 --
@@ -90,33 +373,47 @@ package body System.Pack_83 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_83
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_83;
 
@@ -130,32 +427,46 @@ package body System.Pack_83 is
       E       : Bits_83;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_83;
index a3511943cc92cea6e2bf37f129b66bbb370c3449..0ebcd08dc21c6264f9bf63918bb0d757ffbc1ebd 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_84 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 84 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_84 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_84;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_84 or SetU_84 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_84;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_84 or SetU_84 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_84;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_84 or SetU_84 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_84;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_84 or SetU_84 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_84;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_84 or SetU_84 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_84;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_84 or SetU_84 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_84;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_84 or SetU_84 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_84;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_84 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_84 or SetU_84 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_84 --
@@ -106,33 +501,47 @@ package body System.Pack_84 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_84
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_84;
 
@@ -145,33 +554,47 @@ package body System.Pack_84 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_84
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_84;
 
@@ -185,32 +608,46 @@ package body System.Pack_84 is
       E       : Bits_84;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_84;
@@ -225,32 +662,46 @@ package body System.Pack_84 is
       E       : Bits_84;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_84;
index b700e2e2a6fffa1306f67e5213935a9baa0721ec..2f1f886476d081558d365e8c7613f5798cd049f1 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_85 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 85 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_85 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_85;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_85;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_85;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_85;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_85;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_85;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_85;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_85;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_85 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_85 --
@@ -90,33 +373,47 @@ package body System.Pack_85 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_85
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_85;
 
@@ -130,32 +427,46 @@ package body System.Pack_85 is
       E       : Bits_85;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_85;
index 3bf32d47eff35b14e696266e4fdd587492a3d165..a738372d45e722e7427b30974c985cc1d779948a 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_86 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 86 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_86 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_86;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_86 or SetU_86 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_86;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_86 or SetU_86 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_86;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_86 or SetU_86 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_86;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_86 or SetU_86 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_86;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_86 or SetU_86 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_86;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_86 or SetU_86 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_86;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_86 or SetU_86 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_86;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_86 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_86 or SetU_86 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_86 --
@@ -106,33 +501,47 @@ package body System.Pack_86 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_86
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_86;
 
@@ -145,33 +554,47 @@ package body System.Pack_86 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_86
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_86;
 
@@ -185,32 +608,46 @@ package body System.Pack_86 is
       E       : Bits_86;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_86;
@@ -225,32 +662,46 @@ package body System.Pack_86 is
       E       : Bits_86;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_86;
index 23e460b8e8e4a77ada2de768c3ab5ac3509f6367..5baaa0795e7ee53b2317e969f0cc72038b400642 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_87 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 87 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_87 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_87;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_87;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_87;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_87;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_87;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_87;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_87;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_87;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_87 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_87 --
@@ -90,33 +373,47 @@ package body System.Pack_87 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_87
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_87;
 
@@ -130,32 +427,46 @@ package body System.Pack_87 is
       E       : Bits_87;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_87;
index a17f24840021642d6d0a092ba5d89f184c193689..b66836da3a74f952ad5a4845c4f10378805859b5 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_88 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 88 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_88 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_88;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_88 or SetU_88 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_88;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_88 or SetU_88 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_88;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_88 or SetU_88 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_88;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_88 or SetU_88 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_88;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_88 or SetU_88 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_88;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_88 or SetU_88 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_88;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_88 or SetU_88 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_88;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_88 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_88 or SetU_88 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_88 --
@@ -106,33 +501,47 @@ package body System.Pack_88 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_88
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_88;
 
@@ -145,33 +554,47 @@ package body System.Pack_88 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_88
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_88;
 
@@ -185,32 +608,46 @@ package body System.Pack_88 is
       E       : Bits_88;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_88;
@@ -225,32 +662,46 @@ package body System.Pack_88 is
       E       : Bits_88;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_88;
index 323005c8e2ce92cedbed0811f1c188cf1d479391..399dda5cb2e5758bb474a49849bed3e545c18746 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_89 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 89 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_89 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_89;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_89;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_89;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_89;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_89;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_89;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_89;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_89;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_89 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_89 --
@@ -90,33 +373,47 @@ package body System.Pack_89 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_89
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_89;
 
@@ -130,32 +427,46 @@ package body System.Pack_89 is
       E       : Bits_89;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_89;
index badcd3fb668fcd7e88f9f61334b0cdcb32b0b252..8ea7b0790e429d5773db7f932a3d638988d8b102 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_90 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 90 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_90 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_90;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_90 or SetU_90 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_90;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_90 or SetU_90 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_90;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_90 or SetU_90 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_90;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_90 or SetU_90 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_90;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_90 or SetU_90 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_90;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_90 or SetU_90 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_90;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_90 or SetU_90 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_90;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_90 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_90 or SetU_90 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_90 --
@@ -106,33 +501,47 @@ package body System.Pack_90 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_90
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_90;
 
@@ -145,33 +554,47 @@ package body System.Pack_90 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_90
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_90;
 
@@ -185,32 +608,46 @@ package body System.Pack_90 is
       E       : Bits_90;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_90;
@@ -225,32 +662,46 @@ package body System.Pack_90 is
       E       : Bits_90;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_90;
index 5233fdaf54cae876d337e641b2922b9ae5abd5ae..e62bb765da049ebd8c13cf0e938b6b3c81f9b612 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_91 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 91 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_91 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_91;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_91;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_91;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_91;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_91;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_91;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_91;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_91;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_91 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_91 --
@@ -90,33 +373,47 @@ package body System.Pack_91 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_91
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_91;
 
@@ -130,32 +427,46 @@ package body System.Pack_91 is
       E       : Bits_91;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_91;
index 32f7aef3b1d8607f0c81e7c2107132ff4e8cbcda..129013fd05014e7df17c952fdc5a7daf757a7e5e 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_92 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 92 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_92 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_92;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_92 or SetU_92 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_92;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_92 or SetU_92 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_92;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_92 or SetU_92 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_92;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_92 or SetU_92 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_92;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_92 or SetU_92 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_92;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_92 or SetU_92 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_92;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_92 or SetU_92 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_92;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_92 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_92 or SetU_92 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_92 --
@@ -106,33 +501,47 @@ package body System.Pack_92 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_92
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_92;
 
@@ -145,33 +554,47 @@ package body System.Pack_92 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_92
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_92;
 
@@ -185,32 +608,46 @@ package body System.Pack_92 is
       E       : Bits_92;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_92;
@@ -225,32 +662,46 @@ package body System.Pack_92 is
       E       : Bits_92;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_92;
index 079b1bec4a9fd1819484ff11b6e47b56cce766e4..ac33bf75b706ab7d90c6cf45332d88c4c5f915ad 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_93 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 93 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_93 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_93;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_93;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_93;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_93;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_93;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_93;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_93;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_93;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_93 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_93 --
@@ -90,33 +373,47 @@ package body System.Pack_93 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_93
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_93;
 
@@ -130,32 +427,46 @@ package body System.Pack_93 is
       E       : Bits_93;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_93;
index 0964b378737226bd8a9e36abb7e836006357d302..9c82389432bbb4cdba21711b75bc26566837e767 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_94 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 94 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_94 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_94;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_94 or SetU_94 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_94;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_94 or SetU_94 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_94;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_94 or SetU_94 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_94;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_94 or SetU_94 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_94;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_94 or SetU_94 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_94;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_94 or SetU_94 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_94;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_94 or SetU_94 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_94;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_94 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_94 or SetU_94 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_94 --
@@ -106,33 +501,47 @@ package body System.Pack_94 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_94
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_94;
 
@@ -145,33 +554,47 @@ package body System.Pack_94 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_94
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_94;
 
@@ -185,32 +608,46 @@ package body System.Pack_94 is
       E       : Bits_94;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_94;
@@ -225,32 +662,46 @@ package body System.Pack_94 is
       E       : Bits_94;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_94;
index c81c259b0514940476d25df541ef95fa7cc07842..270b8cd510267d4b1fc439936891c27f4b6a919a 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_95 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 95 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_95 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_95;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_95;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_95;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_95;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_95;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_95;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_95;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_95;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_95 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_95 --
@@ -90,33 +373,47 @@ package body System.Pack_95 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_95
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_95;
 
@@ -130,32 +427,46 @@ package body System.Pack_95 is
       E       : Bits_95;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_95;
index 47bc025d8299e110e946f12f4d87d68607279b2d..c6b8f68d0ac8cf06d85eb318dc360e232a4d4630 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_96 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 96 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_96 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_96;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_96 or SetU_96 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_96;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_96 or SetU_96 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_96;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_96 or SetU_96 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_96;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_96 or SetU_96 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_96;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_96 or SetU_96 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_96;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_96 or SetU_96 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_96;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_96 or SetU_96 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_96;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_96 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_96 or SetU_96 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_96 --
@@ -106,33 +501,47 @@ package body System.Pack_96 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_96
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_96;
 
@@ -145,33 +554,47 @@ package body System.Pack_96 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_96
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_96;
 
@@ -185,32 +608,46 @@ package body System.Pack_96 is
       E       : Bits_96;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_96;
@@ -225,32 +662,46 @@ package body System.Pack_96 is
       E       : Bits_96;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_96;
index 737fc0f9a345860b94943c04da9798ba88b754bb..7976432c698aae0dd7033b104b58ad8c0db090ef 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_97 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 97 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_97 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_97;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_97;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_97;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_97;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_97;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_97;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_97;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_97;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_97 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_97 --
@@ -90,33 +373,47 @@ package body System.Pack_97 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_97
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_97;
 
@@ -130,32 +427,46 @@ package body System.Pack_97 is
       E       : Bits_97;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_97;
index f6d3264d374a744cf7cf155ac4ead44589da770a..f0ce8bc4e2e73c6df8649d3016373af72e7a8a3c 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_98 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 98 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,372 @@ package body System.Pack_98 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_98;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_98 or SetU_98 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_98;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_98 or SetU_98 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_98;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_98 or SetU_98 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_98;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_98 or SetU_98 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_98;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_98 or SetU_98 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_98;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_98 or SetU_98 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_98;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --  The following declarations are for the case where the address
+   --  passed to GetU_98 or SetU_98 is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_98;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,41 +456,41 @@ package body System.Pack_98 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    --  The following declarations are for the case where the address
    --  passed to GetU_98 or SetU_98 is not guaranteed to be aligned.
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
    ------------
    -- Get_98 --
@@ -106,33 +501,47 @@ package body System.Pack_98 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_98
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_98;
 
@@ -145,33 +554,47 @@ package body System.Pack_98 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_98
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_98;
 
@@ -185,32 +608,46 @@ package body System.Pack_98 is
       E       : Bits_98;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_98;
@@ -225,32 +662,46 @@ package body System.Pack_98 is
       E       : Bits_98;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_98;
index 9cc57f10128b7828d665a2fffd8add735cef4795..8621798d87f498e80d1e82d704ed8052e3e09fcf 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_99 is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words 99 bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,260 @@ package body System.Pack_99 is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_99;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_99;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_99;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_99;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_99;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_99;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_99;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_99;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +344,25 @@ package body System.Pack_99 is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
    ------------
    -- Get_99 --
@@ -90,33 +373,47 @@ package body System.Pack_99 is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_99
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_99;
 
@@ -130,32 +427,46 @@ package body System.Pack_99 is
       E       : Bits_99;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_99;
index 540c5196534a61fe615bc93dd71ab5017ab56ebc..659613920266071abb4e428a712183f711cdbaa9 100644 (file)
@@ -35,6 +35,40 @@ with System.Unsigned_Types;
 
 package body System.Pack_@@ is
 
+   --  The high-level idea of the implementation is to overlay a record
+   --  containing components of the same size as that of the component
+   --  of the array, in order words @@ bits, and to access the indexed
+   --  component of the array through the appropriate selected component
+   --  of the record.
+
+   --  The record must be of a fixed size for technical reasons, so we
+   --  effectively overlay a series of contiguous records containing 8
+   --  components (so that their size in bits is a multiple of a byte)
+   --  at the start of the array and access the component in the last
+   --  of them. However, this component in the last record may also be
+   --  mapped to the last component of the array, which means that the
+   --  generated code cannot safely access past it (or its last byte).
+   --  That's why the last record of the series is shortened, so the
+   --  accessed component is always the last component of the record.
+
+   --  A (0)                                               A (N)
+   --  |                                                     |
+   --  V                                                     V
+   --  ---------------------------------------------------------------
+   --  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   --  ---------------------------------------------------------------
+   --
+   --                                                    component K
+   --                                                        |
+   --                                                        V
+   --  ---------------------------------------------------------
+   --  |               |               |               |       |
+   --  ---------------------------------------------------------
+   --         |               |               |             |
+   --      Cluster7        Cluster7        Cluster7     ClusterK
+   --
+   --  where the number of Cluster7 is N / 8 and K is N mod 8.
+
    subtype Bit_Order is System.Bit_Order;
    Reverse_Bit_Order : constant Bit_Order :=
      Bit_Order'Val (1 - Bit_Order'Pos (System.Default_Bit_Order));
@@ -46,11 +80,386 @@ package body System.Pack_@@ is
    use type System.Storage_Elements.Storage_Offset;
    use type System.Unsigned_Types.Unsigned;
 
-   type Cluster is record
+   --------------
+   -- Cluster0 --
+   --------------
+
+   type Cluster0 is record
+      E0 : Bits_@@;
+   end record;
+
+   for Cluster0 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+   end record;
+
+   for Cluster0'Size use Bits * (1 + 0);
+
+   for Cluster0'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC0 is new Address_To_Access_Conversions (Cluster0);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster0 is new Cluster0
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0 is new Address_To_Access_Conversions (Rev_Cluster0);
+
+@even
+   --  The following declarations are for the case where the address
+   --  passed to GetU_@@ or SetU_@@ is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster0U is new Cluster0;
+   for Cluster0U'Alignment use 1;
+
+   package AAC0U is new Address_To_Access_Conversions (Cluster0U);
+
+   type Rev_Cluster0U is new Cluster0U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC0U is new Address_To_Access_Conversions (Rev_Cluster0U);
+
+@/even
+   --------------
+   -- Cluster1 --
+   --------------
+
+   type Cluster1 is record
+      E0, E1 : Bits_@@;
+   end record;
+
+   for Cluster1 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+   end record;
+
+   for Cluster1'Size use Bits * (1 + 1);
+
+   for Cluster1'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC1 is new Address_To_Access_Conversions (Cluster1);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster1 is new Cluster1
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1 is new Address_To_Access_Conversions (Rev_Cluster1);
+
+@even
+   --  The following declarations are for the case where the address
+   --  passed to GetU_@@ or SetU_@@ is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster1U is new Cluster1;
+   for Cluster1U'Alignment use 1;
+
+   package AAC1U is new Address_To_Access_Conversions (Cluster1U);
+
+   type Rev_Cluster1U is new Cluster1U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC1U is new Address_To_Access_Conversions (Rev_Cluster1U);
+
+@/even
+   --------------
+   -- Cluster2 --
+   --------------
+
+   type Cluster2 is record
+      E0, E1, E2 : Bits_@@;
+   end record;
+
+   for Cluster2 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+   end record;
+
+   for Cluster2'Size use Bits * (1 + 2);
+
+   for Cluster2'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC2 is new Address_To_Access_Conversions (Cluster2);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster2 is new Cluster2
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2 is new Address_To_Access_Conversions (Rev_Cluster2);
+
+@even
+   --  The following declarations are for the case where the address
+   --  passed to GetU_@@ or SetU_@@ is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster2U is new Cluster2;
+   for Cluster2U'Alignment use 1;
+
+   package AAC2U is new Address_To_Access_Conversions (Cluster2U);
+
+   type Rev_Cluster2U is new Cluster2U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC2U is new Address_To_Access_Conversions (Rev_Cluster2U);
+
+@/even
+   --------------
+   -- Cluster3 --
+   --------------
+
+   type Cluster3 is record
+      E0, E1, E2, E3 : Bits_@@;
+   end record;
+
+   for Cluster3 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+   end record;
+
+   for Cluster3'Size use Bits * (1 + 3);
+
+   for Cluster3'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC3 is new Address_To_Access_Conversions (Cluster3);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster3 is new Cluster3
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3 is new Address_To_Access_Conversions (Rev_Cluster3);
+
+@even
+   --  The following declarations are for the case where the address
+   --  passed to GetU_@@ or SetU_@@ is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster3U is new Cluster3;
+   for Cluster3U'Alignment use 1;
+
+   package AAC3U is new Address_To_Access_Conversions (Cluster3U);
+
+   type Rev_Cluster3U is new Cluster3U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC3U is new Address_To_Access_Conversions (Rev_Cluster3U);
+
+@/even
+   --------------
+   -- Cluster4 --
+   --------------
+
+   type Cluster4 is record
+      E0, E1, E2, E3, E4 : Bits_@@;
+   end record;
+
+   for Cluster4 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+   end record;
+
+   for Cluster4'Size use Bits * (1 + 4);
+
+   for Cluster4'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC4 is new Address_To_Access_Conversions (Cluster4);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster4 is new Cluster4
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4 is new Address_To_Access_Conversions (Rev_Cluster4);
+
+@even
+   --  The following declarations are for the case where the address
+   --  passed to GetU_@@ or SetU_@@ is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster4U is new Cluster4;
+   for Cluster4U'Alignment use 1;
+
+   package AAC4U is new Address_To_Access_Conversions (Cluster4U);
+
+   type Rev_Cluster4U is new Cluster4U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC4U is new Address_To_Access_Conversions (Rev_Cluster4U);
+
+@/even
+   --------------
+   -- Cluster5 --
+   --------------
+
+   type Cluster5 is record
+      E0, E1, E2, E3, E4, E5 : Bits_@@;
+   end record;
+
+   for Cluster5 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+   end record;
+
+   for Cluster5'Size use Bits * (1 + 5);
+
+   for Cluster5'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC5 is new Address_To_Access_Conversions (Cluster5);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster5 is new Cluster5
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5 is new Address_To_Access_Conversions (Rev_Cluster5);
+
+@even
+   --  The following declarations are for the case where the address
+   --  passed to GetU_@@ or SetU_@@ is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster5U is new Cluster5;
+   for Cluster5U'Alignment use 1;
+
+   package AAC5U is new Address_To_Access_Conversions (Cluster5U);
+
+   type Rev_Cluster5U is new Cluster5U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC5U is new Address_To_Access_Conversions (Rev_Cluster5U);
+
+@/even
+   --------------
+   -- Cluster6 --
+   --------------
+
+   type Cluster6 is record
+      E0, E1, E2, E3, E4, E5, E6 : Bits_@@;
+   end record;
+
+   for Cluster6 use record
+      E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
+      E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
+      E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
+      E3 at 0 range 3 * Bits .. 3 * Bits + Bits - 1;
+      E4 at 0 range 4 * Bits .. 4 * Bits + Bits - 1;
+      E5 at 0 range 5 * Bits .. 5 * Bits + Bits - 1;
+      E6 at 0 range 6 * Bits .. 6 * Bits + Bits - 1;
+   end record;
+
+   for Cluster6'Size use Bits * (1 + 6);
+
+   for Cluster6'Alignment use Integer'Min (Standard'Maximum_Alignment,
+     1 +
+     1 * Boolean'Pos (Bits mod 2 = 0) +
+     2 * Boolean'Pos (Bits mod 4 = 0));
+   --  Use maximum possible alignment, given the bit field size, since this
+   --  will result in the most efficient code possible for the field.
+
+   package AAC6 is new Address_To_Access_Conversions (Cluster6);
+   --  We convert addresses to access values and dereference them instead of
+   --  directly using overlays in order to work around the implementation of
+   --  the RM 13.3(19) clause, which would pessimize the generated code.
+
+   type Rev_Cluster6 is new Cluster6
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6 is new Address_To_Access_Conversions (Rev_Cluster6);
+
+@even
+   --  The following declarations are for the case where the address
+   --  passed to GetU_@@ or SetU_@@ is not guaranteed to be aligned.
+   --  These routines are used when the packed array is itself a
+   --  component of a packed record, and therefore may not be aligned.
+
+   type Cluster6U is new Cluster6;
+   for Cluster6U'Alignment use 1;
+
+   package AAC6U is new Address_To_Access_Conversions (Cluster6U);
+
+   type Rev_Cluster6U is new Cluster6U
+     with Bit_Order            => Reverse_Bit_Order,
+          Scalar_Storage_Order => Reverse_Bit_Order;
+
+   package Rev_AAC6U is new Address_To_Access_Conversions (Rev_Cluster6U);
+
+@/even
+   --------------
+   -- Cluster7 --
+   --------------
+
+   type Cluster7 is record
       E0, E1, E2, E3, E4, E5, E6, E7 : Bits_@@;
    end record;
 
-   for Cluster use record
+   for Cluster7 use record
       E0 at 0 range 0 * Bits .. 0 * Bits + Bits - 1;
       E1 at 0 range 1 * Bits .. 1 * Bits + Bits - 1;
       E2 at 0 range 2 * Bits .. 2 * Bits + Bits - 1;
@@ -61,25 +470,25 @@ package body System.Pack_@@ is
       E7 at 0 range 7 * Bits .. 7 * Bits + Bits - 1;
    end record;
 
-   for Cluster'Size use Bits * 8;
+   for Cluster7'Size use Bits * (1 + 7);
 
-   for Cluster'Alignment use Integer'Min (Standard'Maximum_Alignment,
+   for Cluster7'Alignment use Integer'Min (Standard'Maximum_Alignment,
      1 +
      1 * Boolean'Pos (Bits mod 2 = 0) +
      2 * Boolean'Pos (Bits mod 4 = 0));
    --  Use maximum possible alignment, given the bit field size, since this
    --  will result in the most efficient code possible for the field.
 
-   package AAC is new Address_To_Access_Conversions (Cluster);
+   package AAC7 is new Address_To_Access_Conversions (Cluster7);
    --  We convert addresses to access values and dereference them instead of
    --  directly using overlays in order to work around the implementation of
    --  the RM 13.3(19) clause, which would pessimize the generated code.
 
-   type Rev_Cluster is new Cluster
+   type Rev_Cluster7 is new Cluster7
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AAC is new Address_To_Access_Conversions (Rev_Cluster);
+   package Rev_AAC7 is new Address_To_Access_Conversions (Rev_Cluster7);
 
 @even
    --  The following declarations are for the case where the address
@@ -87,16 +496,16 @@ package body System.Pack_@@ is
    --  These routines are used when the packed array is itself a
    --  component of a packed record, and therefore may not be aligned.
 
-   type ClusterU is new Cluster;
-   for ClusterU'Alignment use 1;
+   type Cluster7U is new Cluster7;
+   for Cluster7U'Alignment use 1;
 
-   package AACU is new Address_To_Access_Conversions (ClusterU);
+   package AAC7U is new Address_To_Access_Conversions (Cluster7U);
 
-   type Rev_ClusterU is new ClusterU
+   type Rev_Cluster7U is new Cluster7U
      with Bit_Order            => Reverse_Bit_Order,
           Scalar_Storage_Order => Reverse_Bit_Order;
 
-   package Rev_AACU is new Address_To_Access_Conversions (Rev_ClusterU);
+   package Rev_AAC7U is new Address_To_Access_Conversions (Rev_Cluster7U);
 
 @/even
    ------------
@@ -108,33 +517,47 @@ package body System.Pack_@@ is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_@@
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end Get_@@;
 
@@ -148,33 +571,47 @@ package body System.Pack_@@ is
       N       : Natural;
       Rev_SSO : Boolean) return Bits_@@
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       return
          (if Rev_SSO then
             (case N07 (Uns (N) mod 8) is
-               when 0 => RC.E0,
-               when 1 => RC.E1,
-               when 2 => RC.E2,
-               when 3 => RC.E3,
-               when 4 => RC.E4,
-               when 5 => RC.E5,
-               when 6 => RC.E6,
-               when 7 => RC.E7)
+               when 0 => RC0.E0,
+               when 1 => RC1.E1,
+               when 2 => RC2.E2,
+               when 3 => RC3.E3,
+               when 4 => RC4.E4,
+               when 5 => RC5.E5,
+               when 6 => RC6.E6,
+               when 7 => RC7.E7)
 
          else
             (case N07 (Uns (N) mod 8) is
-               when 0 => C.E0,
-               when 1 => C.E1,
-               when 2 => C.E2,
-               when 3 => C.E3,
-               when 4 => C.E4,
-               when 5 => C.E5,
-               when 6 => C.E6,
-               when 7 => C.E7)
+               when 0 => C0.E0,
+               when 1 => C1.E1,
+               when 2 => C2.E2,
+               when 3 => C3.E3,
+               when 4 => C4.E4,
+               when 5 => C5.E5,
+               when 6 => C6.E6,
+               when 7 => C7.E7)
          );
    end GetU_@@;
 
@@ -189,32 +626,46 @@ package body System.Pack_@@ is
       E       : Bits_@@;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address         := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AAC.Object_Pointer     := AAC.To_Pointer (A);
-      RC : constant Rev_AAC.Object_Pointer := Rev_AAC.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0.Object_Pointer     := AAC0.To_Pointer (A);
+      C1  : constant AAC1.Object_Pointer     := AAC1.To_Pointer (A);
+      C2  : constant AAC2.Object_Pointer     := AAC2.To_Pointer (A);
+      C3  : constant AAC3.Object_Pointer     := AAC3.To_Pointer (A);
+      C4  : constant AAC4.Object_Pointer     := AAC4.To_Pointer (A);
+      C5  : constant AAC5.Object_Pointer     := AAC5.To_Pointer (A);
+      C6  : constant AAC6.Object_Pointer     := AAC6.To_Pointer (A);
+      C7  : constant AAC7.Object_Pointer     := AAC7.To_Pointer (A);
+      RC0 : constant Rev_AAC0.Object_Pointer := Rev_AAC0.To_Pointer (A);
+      RC1 : constant Rev_AAC1.Object_Pointer := Rev_AAC1.To_Pointer (A);
+      RC2 : constant Rev_AAC2.Object_Pointer := Rev_AAC2.To_Pointer (A);
+      RC3 : constant Rev_AAC3.Object_Pointer := Rev_AAC3.To_Pointer (A);
+      RC4 : constant Rev_AAC4.Object_Pointer := Rev_AAC4.To_Pointer (A);
+      RC5 : constant Rev_AAC5.Object_Pointer := Rev_AAC5.To_Pointer (A);
+      RC6 : constant Rev_AAC6.Object_Pointer := Rev_AAC6.To_Pointer (A);
+      RC7 : constant Rev_AAC7.Object_Pointer := Rev_AAC7.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end Set_@@;
@@ -230,32 +681,46 @@ package body System.Pack_@@ is
       E       : Bits_@@;
       Rev_SSO : Boolean)
    is
-      A  : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
-      C  : constant AACU.Object_Pointer     := AACU.To_Pointer (A);
-      RC : constant Rev_AACU.Object_Pointer := Rev_AACU.To_Pointer (A);
+      A   : constant System.Address          := Arr + Bits * Ofs (Uns (N) / 8);
+      C0  : constant AAC0U.Object_Pointer     := AAC0U.To_Pointer (A);
+      C1  : constant AAC1U.Object_Pointer     := AAC1U.To_Pointer (A);
+      C2  : constant AAC2U.Object_Pointer     := AAC2U.To_Pointer (A);
+      C3  : constant AAC3U.Object_Pointer     := AAC3U.To_Pointer (A);
+      C4  : constant AAC4U.Object_Pointer     := AAC4U.To_Pointer (A);
+      C5  : constant AAC5U.Object_Pointer     := AAC5U.To_Pointer (A);
+      C6  : constant AAC6U.Object_Pointer     := AAC6U.To_Pointer (A);
+      C7  : constant AAC7U.Object_Pointer     := AAC7U.To_Pointer (A);
+      RC0 : constant Rev_AAC0U.Object_Pointer := Rev_AAC0U.To_Pointer (A);
+      RC1 : constant Rev_AAC1U.Object_Pointer := Rev_AAC1U.To_Pointer (A);
+      RC2 : constant Rev_AAC2U.Object_Pointer := Rev_AAC2U.To_Pointer (A);
+      RC3 : constant Rev_AAC3U.Object_Pointer := Rev_AAC3U.To_Pointer (A);
+      RC4 : constant Rev_AAC4U.Object_Pointer := Rev_AAC4U.To_Pointer (A);
+      RC5 : constant Rev_AAC5U.Object_Pointer := Rev_AAC5U.To_Pointer (A);
+      RC6 : constant Rev_AAC6U.Object_Pointer := Rev_AAC6U.To_Pointer (A);
+      RC7 : constant Rev_AAC7U.Object_Pointer := Rev_AAC7U.To_Pointer (A);
 
    begin
       if Rev_SSO then
          case N07 (Uns (N) mod 8) is
-            when 0 => RC.E0 := E;
-            when 1 => RC.E1 := E;
-            when 2 => RC.E2 := E;
-            when 3 => RC.E3 := E;
-            when 4 => RC.E4 := E;
-            when 5 => RC.E5 := E;
-            when 6 => RC.E6 := E;
-            when 7 => RC.E7 := E;
+            when 0 => RC0.E0 := E;
+            when 1 => RC1.E1 := E;
+            when 2 => RC2.E2 := E;
+            when 3 => RC3.E3 := E;
+            when 4 => RC4.E4 := E;
+            when 5 => RC5.E5 := E;
+            when 6 => RC6.E6 := E;
+            when 7 => RC7.E7 := E;
          end case;
       else
          case N07 (Uns (N) mod 8) is
-            when 0 => C.E0 := E;
-            when 1 => C.E1 := E;
-            when 2 => C.E2 := E;
-            when 3 => C.E3 := E;
-            when 4 => C.E4 := E;
-            when 5 => C.E5 := E;
-            when 6 => C.E6 := E;
-            when 7 => C.E7 := E;
+            when 0 => C0.E0 := E;
+            when 1 => C1.E1 := E;
+            when 2 => C2.E2 := E;
+            when 3 => C3.E3 := E;
+            when 4 => C4.E4 := E;
+            when 5 => C5.E5 := E;
+            when 6 => C6.E6 := E;
+            when 7 => C7.E7 := E;
          end case;
       end if;
    end SetU_@@;