diff gcc/ada/libgnat/g-altive.ads @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gcc/ada/libgnat/g-altive.ads	Fri Oct 27 22:46:09 2017 +0900
@@ -0,0 +1,766 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                         G N A T . A L T I V E C                          --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--          Copyright (C) 2004-2017, Free Software Foundation, Inc.         --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
+--                                                                          --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception,   --
+-- version 3.1, as published by the Free Software Foundation.               --
+--                                                                          --
+-- You should have received a copy of the GNU General Public License and    --
+-- a copy of the GCC Runtime Library Exception along with this program;     --
+-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
+-- <http://www.gnu.org/licenses/>.                                          --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
+--                                                                          --
+------------------------------------------------------------------------------
+
+-------------------------
+-- General description --
+-------------------------
+
+--  This is the root of a package hierarchy offering an Ada binding to the
+--  PowerPC AltiVec extensions, a set of 128bit vector types together with a
+--  set of subprograms operating on them. Relevant documents are:
+
+--  o AltiVec Technology, Programming Interface Manual (1999-06)
+--    to which we will refer as [PIM], describes the data types, the
+--    functional interface and the ABI conventions.
+
+--  o AltiVec Technology, Programming Environments Manual (2002-02)
+--    to which we will refer as [PEM], describes the hardware architecture
+--    and instruction set.
+
+--  These documents, as well as a number of others of general interest on the
+--  AltiVec technology, are available from the Motorola/AltiVec Web site at:
+
+--  http://www.freescale.com/altivec
+
+--  The binding interface is structured to allow alternate implementations:
+--  for real AltiVec capable targets, and for other targets. In the latter
+--  case, everything is emulated in software. The two versions are referred
+--  to as:
+
+--  o The Hard binding for AltiVec capable targets (with the appropriate
+--    hardware support and corresponding instruction set)
+
+--  o The Soft binding for other targets (with the low level primitives
+--    emulated in software).
+
+--  In addition, interfaces that are not strictly part of the base AltiVec API
+--  are provided, such as vector conversions to and from array representations,
+--  which are of interest for client applications (e.g. for vector
+--  initialization purposes).
+
+--  Only the soft binding is available today
+
+-----------------------------------------
+-- General package architecture survey --
+-----------------------------------------
+
+--  The various vector representations are all "containers" of elementary
+--  values, the possible types of which are declared in this root package to
+--  be generally accessible.
+
+--  From the user standpoint, the binding materializes as a consistent
+--  hierarchy of units:
+
+--                             GNAT.Altivec
+--                           (component types)
+--                                   |
+--          o----------------o----------------o-------------o
+--          |                |                |             |
+--    Vector_Types   Vector_Operations   Vector_Views   Conversions
+
+--  Users can manipulate vectors through two families of types: Vector
+--  types and View types.
+
+--  Vector types are available through the Vector_Types and Vector_Operations
+--  packages, which implement the core binding to the AltiVec API, as
+--  described in [PIM-2.1 data types] and [PIM-4 AltiVec operations and
+--  predicates].
+
+--  The layout of Vector objects is dependant on the target machine
+--  endianness, and View types were devised to offer a higher level user
+--  interface. With Views, a vector of 4 uints (1, 2, 3, 4) is always declared
+--  with a VUI_View := (Values => (1, 2, 3, 4)), element 1 first, natural
+--  notation to denote the element values, and indexed notation is available
+--  to access individual elements.
+
+--  View types do not represent Altivec vectors per se, in the sense that the
+--  Altivec_Operations are not available for them. They are intended to allow
+--  Vector initializations as well as access to the Vector component values.
+
+--  The GNAT.Altivec.Conversions package is provided to convert a View to the
+--  corresponding Vector and vice-versa.
+
+---------------------------
+-- Underlying principles --
+---------------------------
+
+--  Internally, the binding relies on an abstraction of the Altivec API, a
+--  rich set of functions around a core of low level primitives mapping to
+--  AltiVec instructions. See for instance "vec_add" in [PIM-4.4 Generic and
+--  Specific AltiVec operations], with no less than six result/arguments
+--  combinations of byte vector types that map to "vaddubm".
+
+--  The "soft" version is a software emulation of the low level primitives.
+
+--  The "hard" version would map to real AltiVec instructions via GCC builtins
+--  and inlining.
+
+--  See the "Design Notes" section below for additional details on the
+--  internals.
+
+-------------------
+-- Example usage --
+-------------------
+
+--  Here is a sample program declaring and initializing two vectors, 'add'ing
+--  them and displaying the result components:
+
+--  with GNAT.Altivec.Vector_Types;      use GNAT.Altivec.Vector_Types;
+--  with GNAT.Altivec.Vector_Operations; use GNAT.Altivec.Vector_Operations;
+--  with GNAT.Altivec.Vector_Views;      use GNAT.Altivec.Vector_Views;
+--  with GNAT.Altivec.Conversions;       use GNAT.Altivec.Conversions;
+
+--  use GNAT.Altivec;
+
+--  with Ada.Text_IO; use Ada.Text_IO;
+
+--  procedure Sample is
+--     Va : Vector_Unsigned_Int := To_Vector ((Values => (1, 2, 3, 4)));
+--     Vb : Vector_Unsigned_Int := To_Vector ((Values => (1, 2, 3, 4)));
+
+--     Vs : Vector_Unsigned_Int;
+--     Vs_View : VUI_View;
+--  begin
+--     Vs := Vec_Add (Va, Vb);
+--     Vs_View := To_View (Vs);
+
+--     for I in Vs_View.Values'Range loop
+--        Put_Line (Unsigned_Int'Image (Vs_View.Values (I)));
+--     end loop;
+--  end;
+
+--  $ gnatmake sample.adb
+--  [...]
+--  $ ./sample
+--  2
+--  4
+--  6
+--  8
+
+------------------------------------------------------------------------------
+
+with System;
+
+package GNAT.Altivec is
+
+   --  Definitions of constants and vector/array component types common to all
+   --  the versions of the binding.
+
+   --  All the vector types are 128bits
+
+   VECTOR_BIT : constant := 128;
+
+   -------------------------------------------
+   -- [PIM-2.3.1 Alignment of vector types] --
+   -------------------------------------------
+
+   --  "A defined data item of any vector data type in memory is always
+   --  aligned on a 16-byte boundary. A pointer to any vector data type always
+   --  points to a 16-byte boundary. The compiler is responsible for aligning
+   --  vector data types on 16-byte boundaries."
+
+   VECTOR_ALIGNMENT : constant := Natural'Min (16, Standard'Maximum_Alignment);
+   --  This value is used to set the alignment of vector datatypes in both the
+   --  hard and the soft binding implementations.
+   --
+   --  We want this value to never be greater than 16, because none of the
+   --  binding implementations requires larger alignments and such a value
+   --  would cause useless space to be allocated/wasted for vector objects.
+   --  Furthermore, the alignment of 16 matches the hard binding leading to
+   --  a more faithful emulation.
+   --
+   --  It needs to be exactly 16 for the hard binding, and the initializing
+   --  expression is just right for this purpose since Maximum_Alignment is
+   --  expected to be 16 for the real Altivec ABI.
+   --
+   --  The soft binding doesn't rely on strict 16byte alignment, and we want
+   --  the value to be no greater than Standard'Maximum_Alignment in this case
+   --  to ensure it is supported on every possible target.
+
+   -------------------------------------------------------
+   -- [PIM-2.1] Data Types - Interpretation of contents --
+   -------------------------------------------------------
+
+   ---------------------
+   -- char components --
+   ---------------------
+
+   CHAR_BIT    : constant := 8;
+   SCHAR_MIN   : constant := -2 ** (CHAR_BIT - 1);
+   SCHAR_MAX   : constant := 2 ** (CHAR_BIT - 1) - 1;
+   UCHAR_MAX   : constant := 2 ** CHAR_BIT - 1;
+
+   type unsigned_char is mod UCHAR_MAX + 1;
+   for unsigned_char'Size use CHAR_BIT;
+
+   type signed_char is range SCHAR_MIN .. SCHAR_MAX;
+   for signed_char'Size use CHAR_BIT;
+
+   subtype bool_char is unsigned_char;
+   --  ??? There is a difference here between what the Altivec Technology
+   --  Programming Interface Manual says and what GCC says. In the manual,
+   --  vector_bool_char is a vector_unsigned_char, while in altivec.h it
+   --  is a vector_signed_char.
+
+   bool_char_True  : constant bool_char := bool_char'Last;
+   bool_char_False : constant bool_char := 0;
+
+   ----------------------
+   -- short components --
+   ----------------------
+
+   SHORT_BIT   : constant := 16;
+   SSHORT_MIN  : constant := -2 ** (SHORT_BIT - 1);
+   SSHORT_MAX  : constant := 2 ** (SHORT_BIT - 1) - 1;
+   USHORT_MAX  : constant := 2 ** SHORT_BIT - 1;
+
+   type unsigned_short is mod USHORT_MAX + 1;
+   for unsigned_short'Size use SHORT_BIT;
+
+   subtype unsigned_short_int is unsigned_short;
+
+   type signed_short is range SSHORT_MIN .. SSHORT_MAX;
+   for signed_short'Size use SHORT_BIT;
+
+   subtype signed_short_int is signed_short;
+
+   subtype bool_short is unsigned_short;
+   --  ??? See bool_char
+
+   bool_short_True  : constant bool_short := bool_short'Last;
+   bool_short_False : constant bool_short := 0;
+
+   subtype bool_short_int is bool_short;
+
+   --------------------
+   -- int components --
+   --------------------
+
+   INT_BIT     : constant := 32;
+   SINT_MIN    : constant := -2 ** (INT_BIT - 1);
+   SINT_MAX    : constant := 2 ** (INT_BIT - 1) - 1;
+   UINT_MAX    : constant := 2 ** INT_BIT - 1;
+
+   type unsigned_int is mod UINT_MAX + 1;
+   for unsigned_int'Size use INT_BIT;
+
+   type signed_int is range SINT_MIN .. SINT_MAX;
+   for signed_int'Size use INT_BIT;
+
+   subtype bool_int is unsigned_int;
+   --  ??? See bool_char
+
+   bool_int_True  : constant bool_int := bool_int'Last;
+   bool_int_False : constant bool_int := 0;
+
+   ----------------------
+   -- float components --
+   ----------------------
+
+   FLOAT_BIT   : constant := 32;
+   FLOAT_DIGIT : constant := 6;
+   FLOAT_MIN   : constant := -16#0.FFFF_FF#E+32;
+   FLOAT_MAX   : constant := 16#0.FFFF_FF#E+32;
+
+   type C_float is digits FLOAT_DIGIT range FLOAT_MIN .. FLOAT_MAX;
+   for C_float'Size use FLOAT_BIT;
+   --  Altivec operations always use the standard native floating-point
+   --  support of the target. Note that this means that there may be
+   --  minor differences in results between targets when the floating-
+   --  point implementations are slightly different, as would happen
+   --  with normal non-Altivec floating-point operations. In particular
+   --  the Altivec simulations may yield slightly different results
+   --  from those obtained on a true hardware Altivec target if the
+   --  floating-point implementation is not 100% compatible.
+
+   ----------------------
+   -- pixel components --
+   ----------------------
+
+   subtype pixel is unsigned_short;
+
+   -----------------------------------------------------------
+   -- Subtypes for variants found in the GCC implementation --
+   -----------------------------------------------------------
+
+   subtype c_int is signed_int;
+   subtype c_short is c_int;
+
+   LONG_BIT  : constant := 32;
+   --  Some of the GCC builtins are built with "long" arguments and
+   --  expect SImode to come in.
+
+   SLONG_MIN : constant := -2 ** (LONG_BIT - 1);
+   SLONG_MAX : constant :=  2 ** (LONG_BIT - 1) - 1;
+   ULONG_MAX : constant :=  2 ** LONG_BIT - 1;
+
+   type signed_long   is range SLONG_MIN .. SLONG_MAX;
+   type unsigned_long is mod ULONG_MAX + 1;
+
+   subtype c_long is signed_long;
+
+   subtype c_ptr is System.Address;
+
+   ---------------------------------------------------------
+   -- Access types, for the sake of some argument passing --
+   ---------------------------------------------------------
+
+   type signed_char_ptr    is access all signed_char;
+   type unsigned_char_ptr  is access all unsigned_char;
+
+   type short_ptr          is access all c_short;
+   type signed_short_ptr   is access all signed_short;
+   type unsigned_short_ptr is access all unsigned_short;
+
+   type int_ptr            is access all c_int;
+   type signed_int_ptr     is access all signed_int;
+   type unsigned_int_ptr   is access all unsigned_int;
+
+   type long_ptr           is access all c_long;
+   type signed_long_ptr    is access all signed_long;
+   type unsigned_long_ptr  is access all unsigned_long;
+
+   type float_ptr          is access all Float;
+
+   --
+
+   type const_signed_char_ptr    is access constant signed_char;
+   type const_unsigned_char_ptr  is access constant unsigned_char;
+
+   type const_short_ptr          is access constant c_short;
+   type const_signed_short_ptr   is access constant signed_short;
+   type const_unsigned_short_ptr is access constant unsigned_short;
+
+   type const_int_ptr            is access constant c_int;
+   type const_signed_int_ptr     is access constant signed_int;
+   type const_unsigned_int_ptr   is access constant unsigned_int;
+
+   type const_long_ptr           is access constant c_long;
+   type const_signed_long_ptr    is access constant signed_long;
+   type const_unsigned_long_ptr  is access constant unsigned_long;
+
+   type const_float_ptr          is access constant Float;
+
+   --  Access to const volatile arguments need specialized types
+
+   type volatile_float is new Float;
+   pragma Volatile (volatile_float);
+
+   type volatile_signed_char is new signed_char;
+   pragma Volatile (volatile_signed_char);
+
+   type volatile_unsigned_char is new unsigned_char;
+   pragma Volatile (volatile_unsigned_char);
+
+   type volatile_signed_short is new signed_short;
+   pragma Volatile (volatile_signed_short);
+
+   type volatile_unsigned_short is new unsigned_short;
+   pragma Volatile (volatile_unsigned_short);
+
+   type volatile_signed_int is new signed_int;
+   pragma Volatile (volatile_signed_int);
+
+   type volatile_unsigned_int is new unsigned_int;
+   pragma Volatile (volatile_unsigned_int);
+
+   type volatile_signed_long is new signed_long;
+   pragma Volatile (volatile_signed_long);
+
+   type volatile_unsigned_long is new unsigned_long;
+   pragma Volatile (volatile_unsigned_long);
+
+   type constv_char_ptr           is access constant volatile_signed_char;
+   type constv_signed_char_ptr    is access constant volatile_signed_char;
+   type constv_unsigned_char_ptr  is access constant volatile_unsigned_char;
+
+   type constv_short_ptr          is access constant volatile_signed_short;
+   type constv_signed_short_ptr   is access constant volatile_signed_short;
+   type constv_unsigned_short_ptr is access constant volatile_unsigned_short;
+
+   type constv_int_ptr            is access constant volatile_signed_int;
+   type constv_signed_int_ptr     is access constant volatile_signed_int;
+   type constv_unsigned_int_ptr   is access constant volatile_unsigned_int;
+
+   type constv_long_ptr           is access constant volatile_signed_long;
+   type constv_signed_long_ptr    is access constant volatile_signed_long;
+   type constv_unsigned_long_ptr  is access constant volatile_unsigned_long;
+
+   type constv_float_ptr  is access constant volatile_float;
+
+private
+
+   -----------------------
+   -- Various constants --
+   -----------------------
+
+   CR6_EQ     : constant := 0;
+   CR6_EQ_REV : constant := 1;
+   CR6_LT     : constant := 2;
+   CR6_LT_REV : constant := 3;
+
+end GNAT.Altivec;
+
+--------------------
+--  Design Notes  --
+--------------------
+
+------------------------
+-- General principles --
+------------------------
+
+--  The internal organization has been devised from a number of driving ideas:
+
+--  o From the clients standpoint, the two versions of the binding should be
+--    as easily exchangable as possible,
+
+--  o From the maintenance standpoint, we want to avoid as much code
+--    duplication as possible.
+
+--  o From both standpoints above, we want to maintain a clear interface
+--    separation between the base bindings to the Motorola API and the
+--    additional facilities.
+
+--  The identification of the low level interface is directly inspired by the
+--  the base API organization, basically consisting of a rich set of functions
+--  around a core of low level primitives mapping to AltiVec instructions.
+
+--  See for instance "vec_add" in [PIM-4.4 Generic and Specific AltiVec
+--  operations]: no less than six result/arguments combinations of byte vector
+--  types map to "vaddubm".
+
+--  The "hard" version of the low level primitives map to real AltiVec
+--  instructions via the corresponding GCC builtins. The "soft" version is
+--  a software emulation of those.
+
+---------------------------------------
+-- The Low_Level_Vectors abstraction --
+---------------------------------------
+
+--  The AltiVec C interface spirit is to map a large set of C functions down
+--  to a much smaller set of AltiVec instructions, most of them operating on a
+--  set of vector data types in a transparent manner. See for instance the
+--  case of vec_add, which maps six combinations of result/argument types to
+--  vaddubm for signed/unsigned/bool variants of 'char' components.
+
+--  The GCC implementation of this idiom for C/C++ is to setup builtins
+--  corresponding to the instructions and to expose the C user function as
+--  wrappers around those builtins with no-op type conversions as required.
+--  Typically, for the vec_add case mentioned above, we have (altivec.h):
+--
+--    inline __vector signed char
+--    vec_add (__vector signed char a1, __vector signed char a2)
+--    {
+--      return (__vector signed char)
+--        __builtin_altivec_vaddubm ((__vector signed char) a1,
+--                                   (__vector signed char) a2);
+--    }
+
+--    inline __vector unsigned char
+--    vec_add (__vector __bool char a1, __vector unsigned char a2)
+--    {
+--      return (__vector unsigned char)
+--        __builtin_altivec_vaddubm ((__vector signed char) a1,
+--                                   (__vector signed char) a2);
+--    }
+
+--  The central idea for the Ada bindings is to leverage on the existing GCC
+--  architecture, with the introduction of a Low_Level_Vectors abstraction.
+--  This abstaction acts as a representative of the vector-types and builtins
+--  compiler interface for either the Hard or the Soft case.
+
+--  For the Hard binding, Low_Level_Vectors exposes data types with a GCC
+--  internal translation identical to the "vector ..." C types, and a set of
+--  subprograms mapping straight to the internal GCC builtins.
+
+--  For the Soft binding, Low_Level_Vectors exposes the same set of types
+--  and subprograms, with bodies simulating the instructions behavior.
+
+--  Vector_Types/Operations "simply" bind the user types and operations to
+--  some Low_Level_Vectors implementation, selected in accordance with the
+--  target
+
+--  To achieve a complete Hard/Soft independence in the Vector_Types and
+--  Vector_Operations implementations, both versions of the low level support
+--  are expected to expose a number of facilities:
+
+--  o Private data type declarations for base vector representations embedded
+--    in the user visible vector types, that is:
+
+--      LL_VBC, LL_VUC and LL_VSC
+--        for vector_bool_char, vector_unsigned_char and vector_signed_char
+
+--      LL_VBS, LL_VUS and LL_VSS
+--        for vector_bool_short, vector_unsigned_short and vector_signed_short
+
+--      LL_VBI, LL_VUI and LL_VSI
+--        for vector_bool_int, vector_unsigned_int and vector_signed_int
+
+--    as well as:
+
+--      LL_VP for vector_pixel and LL_VF for vector_float
+
+--  o Primitive operations corresponding to the AltiVec hardware instruction
+--    names, like "vaddubm". The whole set is not described here. The actual
+--    sets are inspired from the GCC builtins which are invoked from GCC's
+--    "altivec.h".
+
+--  o An LL_Altivec convention identifier, specifying the calling convention
+--    to be used to access the aforementioned primitive operations.
+
+--  Besides:
+
+--  o Unchecked_Conversion are expected to be allowed between any pair of
+--    exposed data types, and are expected to have no effect on the value
+--    bit patterns.
+
+-------------------------
+-- Vector views layout --
+-------------------------
+
+--  Vector Views combine intuitive user level ordering for both elements
+--  within a vector and bytes within each element. They basically map to an
+--  array representation where array(i) always represents element (i), in the
+--  natural target representation. This way, a user vector (1, 2, 3, 4) is
+--  represented as:
+
+--                                                       Increasing Addresses
+--  ------------------------------------------------------------------------->
+
+--  | 0x0 0x0 0x0 0x1 | 0x0 0x0 0x0 0x2 | 0x0 0x0 0x0 0x3 | 0x0 0x0 0x0 0x4 |
+--  | V (0), BE       | V (1), BE       | V (2), BE       | V (3), BE       |
+
+--  on a big endian target, and as:
+
+--  | 0x1 0x0 0x0 0x0 | 0x2 0x0 0x0 0x0 | 0x3 0x0 0x0 0x0 | 0x4 0x0 0x0 0x0 |
+--  | V (0), LE       | V (1), LE       | V (2), LE       | V (3), LE       |
+
+--  on a little-endian target
+
+-------------------------
+-- Vector types layout --
+-------------------------
+
+--  In the case of the hard binding, the layout of the vector type in
+--  memory is documented by the Altivec documentation. In the case of the
+--  soft binding, the simplest solution is to represent a vector as an
+--  array of components. This representation can depend on the endianness.
+--  We can consider three possibilities:
+
+--  * First component at the lowest address, components in big endian format.
+--  It is the natural way to represent an array in big endian, and it would
+--  also be the natural way to represent a quad-word integer in big endian.
+
+--  Example:
+
+--  Let V be a vector of unsigned int which value is (1, 2, 3, 4). It is
+--  represented as:
+
+--                                                           Addresses growing
+--  ------------------------------------------------------------------------->
+--  | 0x0 0x0 0x0 0x1 | 0x0 0x0 0x0 0x2 | 0x0 0x0 0x0 0x3 | 0x0 0x0 0x0 0x4 |
+--  | V (0), BE       | V (1), BE       | V (2), BE       | V (3), BE       |
+
+--  * First component at the lowest address, components in little endian
+--  format. It is the natural way to represent an array in little endian.
+
+--  Example:
+
+--  Let V be a vector of unsigned int which value is (1, 2, 3, 4). It is
+--  represented as:
+
+--                                                           Addresses growing
+--  ------------------------------------------------------------------------->
+--  | 0x1 0x0 0x0 0x0 | 0x2 0x0 0x0 0x0 | 0x3 0x0 0x0 0x0 | 0x4 0x0 0x0 0x0 |
+--  | V (0), LE       | V (1), LE       | V (2), LE       | V (3), LE       |
+
+--  * Last component at the lowest address, components in little endian format.
+--  It is the natural way to represent a quad-word integer in little endian.
+
+--  Example:
+
+--  Let V be a vector of unsigned int which value is (1, 2, 3, 4). It is
+--  represented as:
+
+--                                                           Addresses growing
+--  ------------------------------------------------------------------------->
+--  | 0x4 0x0 0x0 0x0 | 0x3 0x0 0x0 0x0 | 0x2 0x0 0x0 0x0 | 0x1 0x0 0x0 0x0 |
+--  | V (3), LE       | V (2), LE       | V (1), LE       | V (0), LE       |
+
+--  There is actually a fourth case (components in big endian, first
+--  component at the lowest address), but it does not have any interesting
+--  properties: it is neither the natural way to represent a quad-word on any
+--  machine, nor the natural way to represent an array on any machine.
+
+--  Example:
+
+--  Let V be a vector of unsigned int which value is (1, 2, 3, 4). It is
+--  represented as:
+
+--                                                           Addresses growing
+--  ------------------------------------------------------------------------->
+--  | 0x0 0x0 0x0 0x4 | 0x0 0x0 0x0 0x3 | 0x0 0x0 0x0 0x2 | 0x0 0x0 0x0 0x1 |
+--  | V (3), BE       | V (2), BE       | V (1), BE       | V (0), BE       |
+
+--  Most of the Altivec operations are specific to a component size, and
+--  can be implemented with any of these three formats. But some operations
+--  are defined by the same Altivec primitive operation for different type
+--  sizes:
+
+--  * operations doing arithmetics on a complete vector, seen as a quad-word;
+--  * operations dealing with memory.
+
+--  Operations on a complete vector:
+--  --------------------------------
+
+--  Examples:
+
+--  vec_sll/vsl : shift left on the entire vector.
+--  vec_slo/vslo: shift left on the entire vector, by octet.
+
+--  Those operations works on vectors seens as a quad-word.
+--  Let us suppose that we have a conversion operation named To_Quad_Word
+--  for converting vector types to a quad-word.
+
+--  Let A be a Altivec vector of 16 components:
+--  A = (A(0), A(1), A(2), A(3), ... , A(14), A(15))
+--  Let B be a Altivec vector of 8 components verifying:
+--  B = (A(0) |8| A(1), A(2) |8| A(3), ... , A(14) |8| A(15))
+--  Let C be a Altivec vector of 4 components verifying:
+--  C = (A(0)  |8| A(1)  |8| A(2)  |8| A(3), ... ,
+--       A(12) |8| A(13) |8| A(14) |8| A(15))
+
+--  (definition: |8| is the concatenation operation between two bytes;
+--  i.e. 0x1 |8| 0x2 = 0x0102)
+
+--  According to [PIM - 4.2 byte ordering], we have the following property:
+--  To_Quad_Word (A) = To_Quad_Word (B) = To_Quad_Word (C)
+
+--  Let To_Type_Of_A be a conversion operation from the type of B to the
+--  type of A.  The quad-word operations are only implemented by one
+--  Altivec primitive operation.  That means that, if QW_Operation is a
+--  quad-word operation, we should have:
+--  QW_Operation (To_Type_of_A (B)) = QW_Operation (A)
+
+--  That is true iff:
+--  To_Quad_Word (To_Type_of_A (B)) = To_Quad_Word (A)
+
+--  As To_Quad_Word is a bijection. we have:
+--  To_Type_of_A (B) = A
+
+--  resp. any combination of A, B, C:
+--  To_Type_of_A (C) = A
+--  To_Type_of_B (A) = B
+--  To_Type_of_C (B) = C
+--  ...
+
+--  Making sure that the properties described above are verified by the
+--  conversion operations between vector types has different implications
+--  depending on the layout of the vector types:
+--  * with format 1 and 3: only a unchecked conversion is needed;
+--  * with format 2 and 4: some reorganisation is needed for conversions
+--  between vector types with different component sizes; that has a cost on the
+--  efficiency, plus the complexity of having different memory pattern for
+--  the same quad-word value, depending on the type.
+
+--  Operation dealing with memory:
+--  ------------------------------
+
+--  These operations are either load operation (vec_ld and the
+--  corresponding primitive operation: vlx) or store operation (vec_st
+--  and the corresponding primitive operation: vstx).
+
+--  According to [PIM 4.4 - vec_ld], those operations take in input
+--  either an access to a vector (e.g. a const_vector_unsigned_int_ptr)
+--  or an access to a flow of components (e.g. a const_unsigned_int_ptr),
+--  relying on the same Altivec primitive operations. That means that both
+--  should have the same representation in memory.
+
+--  For the stream, it is easier to adopt the format of the target. That
+--  means that, in memory, the components of the vector should also have the
+--  format of the target. meaning that we will prefer:
+--  * On a big endian target: format 1 or 4
+--  * On a little endian target: format 2 or 3
+
+--  Conclusion:
+--  -----------
+
+--  To take into consideration the constraint brought about by the routines
+--  operating on quad-words and the routines operating on memory, the best
+--  choice seems to be:
+
+--  * On a big endian target: format 1;
+--  * On a little endian target: format 3.
+
+--  Those layout choices are enforced by GNAT.Altivec.Low_Level_Conversions,
+--  which is the endianness-dependant unit providing conversions between
+--  vector views and vector types.
+
+----------------------
+--  Layouts summary --
+----------------------
+
+--  For a user abstract vector of 4 uints (1, 2, 3, 4), increasing
+--  addresses from left to right:
+
+--  =========================================================================
+--                 BIG ENDIAN TARGET MEMORY LAYOUT for (1, 2, 3, 4)
+--  =========================================================================
+
+--                                    View
+--  -------------------------------------------------------------------------
+--  | 0x0 0x0 0x0 0x1 | 0x0 0x0 0x0 0x2 | 0x0 0x0 0x0 0x3 | 0x0 0x0 0x0 0x4 |
+--  | V (0), BE       | V (1), BE       | V (2), BE       | V (3), BE       |
+--  -------------------------------------------------------------------------
+
+--                                   Vector
+--  -------------------------------------------------------------------------
+--  | 0x0 0x0 0x0 0x1 | 0x0 0x0 0x0 0x2 | 0x0 0x0 0x0 0x3 | 0x0 0x0 0x0 0x4 |
+--  | V (0), BE       | V (1), BE       | V (2), BE       | V (3), BE       |
+--  -------------------------------------------------------------------------
+
+--  =========================================================================
+--              LITTLE ENDIAN TARGET MEMORY LAYOUT for (1, 2, 3, 4)
+--  =========================================================================
+
+--                                    View
+--  -------------------------------------------------------------------------
+--  | 0x1 0x0 0x0 0x0 | 0x2 0x0 0x0 0x0 | 0x3 0x0 0x0 0x0 | 0x4 0x0 0x0 0x0 |
+--  | V (0), LE       | V (1), LE       | V (2), LE       | V (3), LE       |
+
+--                                    Vector
+--  -------------------------------------------------------------------------
+--  | 0x4 0x0 0x0 0x0 | 0x3 0x0 0x0 0x0 | 0x2 0x0 0x0 0x0 | 0x1 0x0 0x0 0x0 |
+--  | V (3), LE       | V (2), LE       | V (1), LE       | V (0), LE       |
+--  -------------------------------------------------------------------------
+
+--  These layouts are common to both the soft and hard implementations on
+--  Altivec capable targets.