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

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
comparison
equal deleted inserted replaced
68:561a7518be6b 111:04ced10e8804
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- G N A T . A L T I V E C --
6 -- --
7 -- S p e c --
8 -- --
9 -- Copyright (C) 2004-2017, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
17 -- --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
21 -- --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
26 -- --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
29 -- --
30 ------------------------------------------------------------------------------
31
32 -------------------------
33 -- General description --
34 -------------------------
35
36 -- This is the root of a package hierarchy offering an Ada binding to the
37 -- PowerPC AltiVec extensions, a set of 128bit vector types together with a
38 -- set of subprograms operating on them. Relevant documents are:
39
40 -- o AltiVec Technology, Programming Interface Manual (1999-06)
41 -- to which we will refer as [PIM], describes the data types, the
42 -- functional interface and the ABI conventions.
43
44 -- o AltiVec Technology, Programming Environments Manual (2002-02)
45 -- to which we will refer as [PEM], describes the hardware architecture
46 -- and instruction set.
47
48 -- These documents, as well as a number of others of general interest on the
49 -- AltiVec technology, are available from the Motorola/AltiVec Web site at:
50
51 -- http://www.freescale.com/altivec
52
53 -- The binding interface is structured to allow alternate implementations:
54 -- for real AltiVec capable targets, and for other targets. In the latter
55 -- case, everything is emulated in software. The two versions are referred
56 -- to as:
57
58 -- o The Hard binding for AltiVec capable targets (with the appropriate
59 -- hardware support and corresponding instruction set)
60
61 -- o The Soft binding for other targets (with the low level primitives
62 -- emulated in software).
63
64 -- In addition, interfaces that are not strictly part of the base AltiVec API
65 -- are provided, such as vector conversions to and from array representations,
66 -- which are of interest for client applications (e.g. for vector
67 -- initialization purposes).
68
69 -- Only the soft binding is available today
70
71 -----------------------------------------
72 -- General package architecture survey --
73 -----------------------------------------
74
75 -- The various vector representations are all "containers" of elementary
76 -- values, the possible types of which are declared in this root package to
77 -- be generally accessible.
78
79 -- From the user standpoint, the binding materializes as a consistent
80 -- hierarchy of units:
81
82 -- GNAT.Altivec
83 -- (component types)
84 -- |
85 -- o----------------o----------------o-------------o
86 -- | | | |
87 -- Vector_Types Vector_Operations Vector_Views Conversions
88
89 -- Users can manipulate vectors through two families of types: Vector
90 -- types and View types.
91
92 -- Vector types are available through the Vector_Types and Vector_Operations
93 -- packages, which implement the core binding to the AltiVec API, as
94 -- described in [PIM-2.1 data types] and [PIM-4 AltiVec operations and
95 -- predicates].
96
97 -- The layout of Vector objects is dependant on the target machine
98 -- endianness, and View types were devised to offer a higher level user
99 -- interface. With Views, a vector of 4 uints (1, 2, 3, 4) is always declared
100 -- with a VUI_View := (Values => (1, 2, 3, 4)), element 1 first, natural
101 -- notation to denote the element values, and indexed notation is available
102 -- to access individual elements.
103
104 -- View types do not represent Altivec vectors per se, in the sense that the
105 -- Altivec_Operations are not available for them. They are intended to allow
106 -- Vector initializations as well as access to the Vector component values.
107
108 -- The GNAT.Altivec.Conversions package is provided to convert a View to the
109 -- corresponding Vector and vice-versa.
110
111 ---------------------------
112 -- Underlying principles --
113 ---------------------------
114
115 -- Internally, the binding relies on an abstraction of the Altivec API, a
116 -- rich set of functions around a core of low level primitives mapping to
117 -- AltiVec instructions. See for instance "vec_add" in [PIM-4.4 Generic and
118 -- Specific AltiVec operations], with no less than six result/arguments
119 -- combinations of byte vector types that map to "vaddubm".
120
121 -- The "soft" version is a software emulation of the low level primitives.
122
123 -- The "hard" version would map to real AltiVec instructions via GCC builtins
124 -- and inlining.
125
126 -- See the "Design Notes" section below for additional details on the
127 -- internals.
128
129 -------------------
130 -- Example usage --
131 -------------------
132
133 -- Here is a sample program declaring and initializing two vectors, 'add'ing
134 -- them and displaying the result components:
135
136 -- with GNAT.Altivec.Vector_Types; use GNAT.Altivec.Vector_Types;
137 -- with GNAT.Altivec.Vector_Operations; use GNAT.Altivec.Vector_Operations;
138 -- with GNAT.Altivec.Vector_Views; use GNAT.Altivec.Vector_Views;
139 -- with GNAT.Altivec.Conversions; use GNAT.Altivec.Conversions;
140
141 -- use GNAT.Altivec;
142
143 -- with Ada.Text_IO; use Ada.Text_IO;
144
145 -- procedure Sample is
146 -- Va : Vector_Unsigned_Int := To_Vector ((Values => (1, 2, 3, 4)));
147 -- Vb : Vector_Unsigned_Int := To_Vector ((Values => (1, 2, 3, 4)));
148
149 -- Vs : Vector_Unsigned_Int;
150 -- Vs_View : VUI_View;
151 -- begin
152 -- Vs := Vec_Add (Va, Vb);
153 -- Vs_View := To_View (Vs);
154
155 -- for I in Vs_View.Values'Range loop
156 -- Put_Line (Unsigned_Int'Image (Vs_View.Values (I)));
157 -- end loop;
158 -- end;
159
160 -- $ gnatmake sample.adb
161 -- [...]
162 -- $ ./sample
163 -- 2
164 -- 4
165 -- 6
166 -- 8
167
168 ------------------------------------------------------------------------------
169
170 with System;
171
172 package GNAT.Altivec is
173
174 -- Definitions of constants and vector/array component types common to all
175 -- the versions of the binding.
176
177 -- All the vector types are 128bits
178
179 VECTOR_BIT : constant := 128;
180
181 -------------------------------------------
182 -- [PIM-2.3.1 Alignment of vector types] --
183 -------------------------------------------
184
185 -- "A defined data item of any vector data type in memory is always
186 -- aligned on a 16-byte boundary. A pointer to any vector data type always
187 -- points to a 16-byte boundary. The compiler is responsible for aligning
188 -- vector data types on 16-byte boundaries."
189
190 VECTOR_ALIGNMENT : constant := Natural'Min (16, Standard'Maximum_Alignment);
191 -- This value is used to set the alignment of vector datatypes in both the
192 -- hard and the soft binding implementations.
193 --
194 -- We want this value to never be greater than 16, because none of the
195 -- binding implementations requires larger alignments and such a value
196 -- would cause useless space to be allocated/wasted for vector objects.
197 -- Furthermore, the alignment of 16 matches the hard binding leading to
198 -- a more faithful emulation.
199 --
200 -- It needs to be exactly 16 for the hard binding, and the initializing
201 -- expression is just right for this purpose since Maximum_Alignment is
202 -- expected to be 16 for the real Altivec ABI.
203 --
204 -- The soft binding doesn't rely on strict 16byte alignment, and we want
205 -- the value to be no greater than Standard'Maximum_Alignment in this case
206 -- to ensure it is supported on every possible target.
207
208 -------------------------------------------------------
209 -- [PIM-2.1] Data Types - Interpretation of contents --
210 -------------------------------------------------------
211
212 ---------------------
213 -- char components --
214 ---------------------
215
216 CHAR_BIT : constant := 8;
217 SCHAR_MIN : constant := -2 ** (CHAR_BIT - 1);
218 SCHAR_MAX : constant := 2 ** (CHAR_BIT - 1) - 1;
219 UCHAR_MAX : constant := 2 ** CHAR_BIT - 1;
220
221 type unsigned_char is mod UCHAR_MAX + 1;
222 for unsigned_char'Size use CHAR_BIT;
223
224 type signed_char is range SCHAR_MIN .. SCHAR_MAX;
225 for signed_char'Size use CHAR_BIT;
226
227 subtype bool_char is unsigned_char;
228 -- ??? There is a difference here between what the Altivec Technology
229 -- Programming Interface Manual says and what GCC says. In the manual,
230 -- vector_bool_char is a vector_unsigned_char, while in altivec.h it
231 -- is a vector_signed_char.
232
233 bool_char_True : constant bool_char := bool_char'Last;
234 bool_char_False : constant bool_char := 0;
235
236 ----------------------
237 -- short components --
238 ----------------------
239
240 SHORT_BIT : constant := 16;
241 SSHORT_MIN : constant := -2 ** (SHORT_BIT - 1);
242 SSHORT_MAX : constant := 2 ** (SHORT_BIT - 1) - 1;
243 USHORT_MAX : constant := 2 ** SHORT_BIT - 1;
244
245 type unsigned_short is mod USHORT_MAX + 1;
246 for unsigned_short'Size use SHORT_BIT;
247
248 subtype unsigned_short_int is unsigned_short;
249
250 type signed_short is range SSHORT_MIN .. SSHORT_MAX;
251 for signed_short'Size use SHORT_BIT;
252
253 subtype signed_short_int is signed_short;
254
255 subtype bool_short is unsigned_short;
256 -- ??? See bool_char
257
258 bool_short_True : constant bool_short := bool_short'Last;
259 bool_short_False : constant bool_short := 0;
260
261 subtype bool_short_int is bool_short;
262
263 --------------------
264 -- int components --
265 --------------------
266
267 INT_BIT : constant := 32;
268 SINT_MIN : constant := -2 ** (INT_BIT - 1);
269 SINT_MAX : constant := 2 ** (INT_BIT - 1) - 1;
270 UINT_MAX : constant := 2 ** INT_BIT - 1;
271
272 type unsigned_int is mod UINT_MAX + 1;
273 for unsigned_int'Size use INT_BIT;
274
275 type signed_int is range SINT_MIN .. SINT_MAX;
276 for signed_int'Size use INT_BIT;
277
278 subtype bool_int is unsigned_int;
279 -- ??? See bool_char
280
281 bool_int_True : constant bool_int := bool_int'Last;
282 bool_int_False : constant bool_int := 0;
283
284 ----------------------
285 -- float components --
286 ----------------------
287
288 FLOAT_BIT : constant := 32;
289 FLOAT_DIGIT : constant := 6;
290 FLOAT_MIN : constant := -16#0.FFFF_FF#E+32;
291 FLOAT_MAX : constant := 16#0.FFFF_FF#E+32;
292
293 type C_float is digits FLOAT_DIGIT range FLOAT_MIN .. FLOAT_MAX;
294 for C_float'Size use FLOAT_BIT;
295 -- Altivec operations always use the standard native floating-point
296 -- support of the target. Note that this means that there may be
297 -- minor differences in results between targets when the floating-
298 -- point implementations are slightly different, as would happen
299 -- with normal non-Altivec floating-point operations. In particular
300 -- the Altivec simulations may yield slightly different results
301 -- from those obtained on a true hardware Altivec target if the
302 -- floating-point implementation is not 100% compatible.
303
304 ----------------------
305 -- pixel components --
306 ----------------------
307
308 subtype pixel is unsigned_short;
309
310 -----------------------------------------------------------
311 -- Subtypes for variants found in the GCC implementation --
312 -----------------------------------------------------------
313
314 subtype c_int is signed_int;
315 subtype c_short is c_int;
316
317 LONG_BIT : constant := 32;
318 -- Some of the GCC builtins are built with "long" arguments and
319 -- expect SImode to come in.
320
321 SLONG_MIN : constant := -2 ** (LONG_BIT - 1);
322 SLONG_MAX : constant := 2 ** (LONG_BIT - 1) - 1;
323 ULONG_MAX : constant := 2 ** LONG_BIT - 1;
324
325 type signed_long is range SLONG_MIN .. SLONG_MAX;
326 type unsigned_long is mod ULONG_MAX + 1;
327
328 subtype c_long is signed_long;
329
330 subtype c_ptr is System.Address;
331
332 ---------------------------------------------------------
333 -- Access types, for the sake of some argument passing --
334 ---------------------------------------------------------
335
336 type signed_char_ptr is access all signed_char;
337 type unsigned_char_ptr is access all unsigned_char;
338
339 type short_ptr is access all c_short;
340 type signed_short_ptr is access all signed_short;
341 type unsigned_short_ptr is access all unsigned_short;
342
343 type int_ptr is access all c_int;
344 type signed_int_ptr is access all signed_int;
345 type unsigned_int_ptr is access all unsigned_int;
346
347 type long_ptr is access all c_long;
348 type signed_long_ptr is access all signed_long;
349 type unsigned_long_ptr is access all unsigned_long;
350
351 type float_ptr is access all Float;
352
353 --
354
355 type const_signed_char_ptr is access constant signed_char;
356 type const_unsigned_char_ptr is access constant unsigned_char;
357
358 type const_short_ptr is access constant c_short;
359 type const_signed_short_ptr is access constant signed_short;
360 type const_unsigned_short_ptr is access constant unsigned_short;
361
362 type const_int_ptr is access constant c_int;
363 type const_signed_int_ptr is access constant signed_int;
364 type const_unsigned_int_ptr is access constant unsigned_int;
365
366 type const_long_ptr is access constant c_long;
367 type const_signed_long_ptr is access constant signed_long;
368 type const_unsigned_long_ptr is access constant unsigned_long;
369
370 type const_float_ptr is access constant Float;
371
372 -- Access to const volatile arguments need specialized types
373
374 type volatile_float is new Float;
375 pragma Volatile (volatile_float);
376
377 type volatile_signed_char is new signed_char;
378 pragma Volatile (volatile_signed_char);
379
380 type volatile_unsigned_char is new unsigned_char;
381 pragma Volatile (volatile_unsigned_char);
382
383 type volatile_signed_short is new signed_short;
384 pragma Volatile (volatile_signed_short);
385
386 type volatile_unsigned_short is new unsigned_short;
387 pragma Volatile (volatile_unsigned_short);
388
389 type volatile_signed_int is new signed_int;
390 pragma Volatile (volatile_signed_int);
391
392 type volatile_unsigned_int is new unsigned_int;
393 pragma Volatile (volatile_unsigned_int);
394
395 type volatile_signed_long is new signed_long;
396 pragma Volatile (volatile_signed_long);
397
398 type volatile_unsigned_long is new unsigned_long;
399 pragma Volatile (volatile_unsigned_long);
400
401 type constv_char_ptr is access constant volatile_signed_char;
402 type constv_signed_char_ptr is access constant volatile_signed_char;
403 type constv_unsigned_char_ptr is access constant volatile_unsigned_char;
404
405 type constv_short_ptr is access constant volatile_signed_short;
406 type constv_signed_short_ptr is access constant volatile_signed_short;
407 type constv_unsigned_short_ptr is access constant volatile_unsigned_short;
408
409 type constv_int_ptr is access constant volatile_signed_int;
410 type constv_signed_int_ptr is access constant volatile_signed_int;
411 type constv_unsigned_int_ptr is access constant volatile_unsigned_int;
412
413 type constv_long_ptr is access constant volatile_signed_long;
414 type constv_signed_long_ptr is access constant volatile_signed_long;
415 type constv_unsigned_long_ptr is access constant volatile_unsigned_long;
416
417 type constv_float_ptr is access constant volatile_float;
418
419 private
420
421 -----------------------
422 -- Various constants --
423 -----------------------
424
425 CR6_EQ : constant := 0;
426 CR6_EQ_REV : constant := 1;
427 CR6_LT : constant := 2;
428 CR6_LT_REV : constant := 3;
429
430 end GNAT.Altivec;
431
432 --------------------
433 -- Design Notes --
434 --------------------
435
436 ------------------------
437 -- General principles --
438 ------------------------
439
440 -- The internal organization has been devised from a number of driving ideas:
441
442 -- o From the clients standpoint, the two versions of the binding should be
443 -- as easily exchangable as possible,
444
445 -- o From the maintenance standpoint, we want to avoid as much code
446 -- duplication as possible.
447
448 -- o From both standpoints above, we want to maintain a clear interface
449 -- separation between the base bindings to the Motorola API and the
450 -- additional facilities.
451
452 -- The identification of the low level interface is directly inspired by the
453 -- the base API organization, basically consisting of a rich set of functions
454 -- around a core of low level primitives mapping to AltiVec instructions.
455
456 -- See for instance "vec_add" in [PIM-4.4 Generic and Specific AltiVec
457 -- operations]: no less than six result/arguments combinations of byte vector
458 -- types map to "vaddubm".
459
460 -- The "hard" version of the low level primitives map to real AltiVec
461 -- instructions via the corresponding GCC builtins. The "soft" version is
462 -- a software emulation of those.
463
464 ---------------------------------------
465 -- The Low_Level_Vectors abstraction --
466 ---------------------------------------
467
468 -- The AltiVec C interface spirit is to map a large set of C functions down
469 -- to a much smaller set of AltiVec instructions, most of them operating on a
470 -- set of vector data types in a transparent manner. See for instance the
471 -- case of vec_add, which maps six combinations of result/argument types to
472 -- vaddubm for signed/unsigned/bool variants of 'char' components.
473
474 -- The GCC implementation of this idiom for C/C++ is to setup builtins
475 -- corresponding to the instructions and to expose the C user function as
476 -- wrappers around those builtins with no-op type conversions as required.
477 -- Typically, for the vec_add case mentioned above, we have (altivec.h):
478 --
479 -- inline __vector signed char
480 -- vec_add (__vector signed char a1, __vector signed char a2)
481 -- {
482 -- return (__vector signed char)
483 -- __builtin_altivec_vaddubm ((__vector signed char) a1,
484 -- (__vector signed char) a2);
485 -- }
486
487 -- inline __vector unsigned char
488 -- vec_add (__vector __bool char a1, __vector unsigned char a2)
489 -- {
490 -- return (__vector unsigned char)
491 -- __builtin_altivec_vaddubm ((__vector signed char) a1,
492 -- (__vector signed char) a2);
493 -- }
494
495 -- The central idea for the Ada bindings is to leverage on the existing GCC
496 -- architecture, with the introduction of a Low_Level_Vectors abstraction.
497 -- This abstaction acts as a representative of the vector-types and builtins
498 -- compiler interface for either the Hard or the Soft case.
499
500 -- For the Hard binding, Low_Level_Vectors exposes data types with a GCC
501 -- internal translation identical to the "vector ..." C types, and a set of
502 -- subprograms mapping straight to the internal GCC builtins.
503
504 -- For the Soft binding, Low_Level_Vectors exposes the same set of types
505 -- and subprograms, with bodies simulating the instructions behavior.
506
507 -- Vector_Types/Operations "simply" bind the user types and operations to
508 -- some Low_Level_Vectors implementation, selected in accordance with the
509 -- target
510
511 -- To achieve a complete Hard/Soft independence in the Vector_Types and
512 -- Vector_Operations implementations, both versions of the low level support
513 -- are expected to expose a number of facilities:
514
515 -- o Private data type declarations for base vector representations embedded
516 -- in the user visible vector types, that is:
517
518 -- LL_VBC, LL_VUC and LL_VSC
519 -- for vector_bool_char, vector_unsigned_char and vector_signed_char
520
521 -- LL_VBS, LL_VUS and LL_VSS
522 -- for vector_bool_short, vector_unsigned_short and vector_signed_short
523
524 -- LL_VBI, LL_VUI and LL_VSI
525 -- for vector_bool_int, vector_unsigned_int and vector_signed_int
526
527 -- as well as:
528
529 -- LL_VP for vector_pixel and LL_VF for vector_float
530
531 -- o Primitive operations corresponding to the AltiVec hardware instruction
532 -- names, like "vaddubm". The whole set is not described here. The actual
533 -- sets are inspired from the GCC builtins which are invoked from GCC's
534 -- "altivec.h".
535
536 -- o An LL_Altivec convention identifier, specifying the calling convention
537 -- to be used to access the aforementioned primitive operations.
538
539 -- Besides:
540
541 -- o Unchecked_Conversion are expected to be allowed between any pair of
542 -- exposed data types, and are expected to have no effect on the value
543 -- bit patterns.
544
545 -------------------------
546 -- Vector views layout --
547 -------------------------
548
549 -- Vector Views combine intuitive user level ordering for both elements
550 -- within a vector and bytes within each element. They basically map to an
551 -- array representation where array(i) always represents element (i), in the
552 -- natural target representation. This way, a user vector (1, 2, 3, 4) is
553 -- represented as:
554
555 -- Increasing Addresses
556 -- ------------------------------------------------------------------------->
557
558 -- | 0x0 0x0 0x0 0x1 | 0x0 0x0 0x0 0x2 | 0x0 0x0 0x0 0x3 | 0x0 0x0 0x0 0x4 |
559 -- | V (0), BE | V (1), BE | V (2), BE | V (3), BE |
560
561 -- on a big endian target, and as:
562
563 -- | 0x1 0x0 0x0 0x0 | 0x2 0x0 0x0 0x0 | 0x3 0x0 0x0 0x0 | 0x4 0x0 0x0 0x0 |
564 -- | V (0), LE | V (1), LE | V (2), LE | V (3), LE |
565
566 -- on a little-endian target
567
568 -------------------------
569 -- Vector types layout --
570 -------------------------
571
572 -- In the case of the hard binding, the layout of the vector type in
573 -- memory is documented by the Altivec documentation. In the case of the
574 -- soft binding, the simplest solution is to represent a vector as an
575 -- array of components. This representation can depend on the endianness.
576 -- We can consider three possibilities:
577
578 -- * First component at the lowest address, components in big endian format.
579 -- It is the natural way to represent an array in big endian, and it would
580 -- also be the natural way to represent a quad-word integer in big endian.
581
582 -- Example:
583
584 -- Let V be a vector of unsigned int which value is (1, 2, 3, 4). It is
585 -- represented as:
586
587 -- Addresses growing
588 -- ------------------------------------------------------------------------->
589 -- | 0x0 0x0 0x0 0x1 | 0x0 0x0 0x0 0x2 | 0x0 0x0 0x0 0x3 | 0x0 0x0 0x0 0x4 |
590 -- | V (0), BE | V (1), BE | V (2), BE | V (3), BE |
591
592 -- * First component at the lowest address, components in little endian
593 -- format. It is the natural way to represent an array in little endian.
594
595 -- Example:
596
597 -- Let V be a vector of unsigned int which value is (1, 2, 3, 4). It is
598 -- represented as:
599
600 -- Addresses growing
601 -- ------------------------------------------------------------------------->
602 -- | 0x1 0x0 0x0 0x0 | 0x2 0x0 0x0 0x0 | 0x3 0x0 0x0 0x0 | 0x4 0x0 0x0 0x0 |
603 -- | V (0), LE | V (1), LE | V (2), LE | V (3), LE |
604
605 -- * Last component at the lowest address, components in little endian format.
606 -- It is the natural way to represent a quad-word integer in little endian.
607
608 -- Example:
609
610 -- Let V be a vector of unsigned int which value is (1, 2, 3, 4). It is
611 -- represented as:
612
613 -- Addresses growing
614 -- ------------------------------------------------------------------------->
615 -- | 0x4 0x0 0x0 0x0 | 0x3 0x0 0x0 0x0 | 0x2 0x0 0x0 0x0 | 0x1 0x0 0x0 0x0 |
616 -- | V (3), LE | V (2), LE | V (1), LE | V (0), LE |
617
618 -- There is actually a fourth case (components in big endian, first
619 -- component at the lowest address), but it does not have any interesting
620 -- properties: it is neither the natural way to represent a quad-word on any
621 -- machine, nor the natural way to represent an array on any machine.
622
623 -- Example:
624
625 -- Let V be a vector of unsigned int which value is (1, 2, 3, 4). It is
626 -- represented as:
627
628 -- Addresses growing
629 -- ------------------------------------------------------------------------->
630 -- | 0x0 0x0 0x0 0x4 | 0x0 0x0 0x0 0x3 | 0x0 0x0 0x0 0x2 | 0x0 0x0 0x0 0x1 |
631 -- | V (3), BE | V (2), BE | V (1), BE | V (0), BE |
632
633 -- Most of the Altivec operations are specific to a component size, and
634 -- can be implemented with any of these three formats. But some operations
635 -- are defined by the same Altivec primitive operation for different type
636 -- sizes:
637
638 -- * operations doing arithmetics on a complete vector, seen as a quad-word;
639 -- * operations dealing with memory.
640
641 -- Operations on a complete vector:
642 -- --------------------------------
643
644 -- Examples:
645
646 -- vec_sll/vsl : shift left on the entire vector.
647 -- vec_slo/vslo: shift left on the entire vector, by octet.
648
649 -- Those operations works on vectors seens as a quad-word.
650 -- Let us suppose that we have a conversion operation named To_Quad_Word
651 -- for converting vector types to a quad-word.
652
653 -- Let A be a Altivec vector of 16 components:
654 -- A = (A(0), A(1), A(2), A(3), ... , A(14), A(15))
655 -- Let B be a Altivec vector of 8 components verifying:
656 -- B = (A(0) |8| A(1), A(2) |8| A(3), ... , A(14) |8| A(15))
657 -- Let C be a Altivec vector of 4 components verifying:
658 -- C = (A(0) |8| A(1) |8| A(2) |8| A(3), ... ,
659 -- A(12) |8| A(13) |8| A(14) |8| A(15))
660
661 -- (definition: |8| is the concatenation operation between two bytes;
662 -- i.e. 0x1 |8| 0x2 = 0x0102)
663
664 -- According to [PIM - 4.2 byte ordering], we have the following property:
665 -- To_Quad_Word (A) = To_Quad_Word (B) = To_Quad_Word (C)
666
667 -- Let To_Type_Of_A be a conversion operation from the type of B to the
668 -- type of A. The quad-word operations are only implemented by one
669 -- Altivec primitive operation. That means that, if QW_Operation is a
670 -- quad-word operation, we should have:
671 -- QW_Operation (To_Type_of_A (B)) = QW_Operation (A)
672
673 -- That is true iff:
674 -- To_Quad_Word (To_Type_of_A (B)) = To_Quad_Word (A)
675
676 -- As To_Quad_Word is a bijection. we have:
677 -- To_Type_of_A (B) = A
678
679 -- resp. any combination of A, B, C:
680 -- To_Type_of_A (C) = A
681 -- To_Type_of_B (A) = B
682 -- To_Type_of_C (B) = C
683 -- ...
684
685 -- Making sure that the properties described above are verified by the
686 -- conversion operations between vector types has different implications
687 -- depending on the layout of the vector types:
688 -- * with format 1 and 3: only a unchecked conversion is needed;
689 -- * with format 2 and 4: some reorganisation is needed for conversions
690 -- between vector types with different component sizes; that has a cost on the
691 -- efficiency, plus the complexity of having different memory pattern for
692 -- the same quad-word value, depending on the type.
693
694 -- Operation dealing with memory:
695 -- ------------------------------
696
697 -- These operations are either load operation (vec_ld and the
698 -- corresponding primitive operation: vlx) or store operation (vec_st
699 -- and the corresponding primitive operation: vstx).
700
701 -- According to [PIM 4.4 - vec_ld], those operations take in input
702 -- either an access to a vector (e.g. a const_vector_unsigned_int_ptr)
703 -- or an access to a flow of components (e.g. a const_unsigned_int_ptr),
704 -- relying on the same Altivec primitive operations. That means that both
705 -- should have the same representation in memory.
706
707 -- For the stream, it is easier to adopt the format of the target. That
708 -- means that, in memory, the components of the vector should also have the
709 -- format of the target. meaning that we will prefer:
710 -- * On a big endian target: format 1 or 4
711 -- * On a little endian target: format 2 or 3
712
713 -- Conclusion:
714 -- -----------
715
716 -- To take into consideration the constraint brought about by the routines
717 -- operating on quad-words and the routines operating on memory, the best
718 -- choice seems to be:
719
720 -- * On a big endian target: format 1;
721 -- * On a little endian target: format 3.
722
723 -- Those layout choices are enforced by GNAT.Altivec.Low_Level_Conversions,
724 -- which is the endianness-dependant unit providing conversions between
725 -- vector views and vector types.
726
727 ----------------------
728 -- Layouts summary --
729 ----------------------
730
731 -- For a user abstract vector of 4 uints (1, 2, 3, 4), increasing
732 -- addresses from left to right:
733
734 -- =========================================================================
735 -- BIG ENDIAN TARGET MEMORY LAYOUT for (1, 2, 3, 4)
736 -- =========================================================================
737
738 -- View
739 -- -------------------------------------------------------------------------
740 -- | 0x0 0x0 0x0 0x1 | 0x0 0x0 0x0 0x2 | 0x0 0x0 0x0 0x3 | 0x0 0x0 0x0 0x4 |
741 -- | V (0), BE | V (1), BE | V (2), BE | V (3), BE |
742 -- -------------------------------------------------------------------------
743
744 -- Vector
745 -- -------------------------------------------------------------------------
746 -- | 0x0 0x0 0x0 0x1 | 0x0 0x0 0x0 0x2 | 0x0 0x0 0x0 0x3 | 0x0 0x0 0x0 0x4 |
747 -- | V (0), BE | V (1), BE | V (2), BE | V (3), BE |
748 -- -------------------------------------------------------------------------
749
750 -- =========================================================================
751 -- LITTLE ENDIAN TARGET MEMORY LAYOUT for (1, 2, 3, 4)
752 -- =========================================================================
753
754 -- View
755 -- -------------------------------------------------------------------------
756 -- | 0x1 0x0 0x0 0x0 | 0x2 0x0 0x0 0x0 | 0x3 0x0 0x0 0x0 | 0x4 0x0 0x0 0x0 |
757 -- | V (0), LE | V (1), LE | V (2), LE | V (3), LE |
758
759 -- Vector
760 -- -------------------------------------------------------------------------
761 -- | 0x4 0x0 0x0 0x0 | 0x3 0x0 0x0 0x0 | 0x2 0x0 0x0 0x0 | 0x1 0x0 0x0 0x0 |
762 -- | V (3), LE | V (2), LE | V (1), LE | V (0), LE |
763 -- -------------------------------------------------------------------------
764
765 -- These layouts are common to both the soft and hard implementations on
766 -- Altivec capable targets.