1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- S Y S T E M . S C A L A R _ V A L U E S --
9 -- Copyright (C) 2003-2009, Free Software Foundation, Inc. --
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. --
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. --
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/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 with Ada
.Unchecked_Conversion
;
34 package body System
.Scalar_Values
is
40 procedure Initialize
(Mode1
: Character; Mode2
: Character) is
41 C1
: Character := Mode1
;
42 C2
: Character := Mode2
;
44 procedure Get_Env_Value_Ptr
(Name
, Length
, Ptr
: Address
);
45 pragma Import
(C
, Get_Env_Value_Ptr
, "__gnat_getenv");
47 subtype String2
is String (1 .. 2);
48 type String2_Ptr
is access all String2
;
50 Env_Value_Ptr
: aliased String2_Ptr
;
51 Env_Value_Length
: aliased Integer;
53 EV_Val
: aliased constant String :=
54 "GNAT_INIT_SCALARS" & ASCII
.NUL
;
58 EFloat
: constant Boolean := Long_Long_Float'Size > Long_Float'Size;
59 -- Set True if we are on an x86 with 96-bit floats for extended
61 AFloat
: constant Boolean :=
62 Long_Float'Size = 48 and then Long_Long_Float'Size = 48;
63 -- Set True if we are on an AAMP with 48-bit extended floating point
65 type ByteLF
is array (0 .. 7 - 2 * Boolean'Pos (AFloat
)) of Byte1
;
67 for ByteLF
'Component_Size use 8;
69 -- Type used to hold Long_Float values on all targets and to initialize
70 -- 48-bit Long_Float values used on AAMP. On AAMP, this type is 6 bytes.
71 -- On other targets the type is 8 bytes, and type Byte8 is used for
72 -- values that are then converted to ByteLF.
74 pragma Warnings
(Off
); -- why ???
75 function To_ByteLF
is new Ada
.Unchecked_Conversion
(Byte8
, ByteLF
);
79 array (0 .. 7 + 4 * Boolean'Pos (EFloat
) - 2 * Boolean'Pos (AFloat
))
82 for ByteLLF
'Component_Size use 8;
84 -- Type used to initialize Long_Long_Float values used on x86 and
85 -- any other target with the same 80-bit floating-point values that
86 -- GCC always stores in 96-bits. Note that we are assuming Intel
87 -- format little-endian addressing for this type. On non-Intel
88 -- architectures, this is the same length as Byte8 and holds
89 -- a Long_Float value.
91 -- The following variables are used to initialize the float values
92 -- by overlay. We can't assign directly to the float values, since
93 -- we may be assigning signalling Nan's that will cause a trap if
94 -- loaded into a floating-point register.
96 IV_Isf
: aliased Byte4
; -- Initialize short float
97 IV_Ifl
: aliased Byte4
; -- Initialize float
98 IV_Ilf
: aliased ByteLF
; -- Initialize long float
99 IV_Ill
: aliased ByteLLF
; -- Initialize long long float
101 for IV_Isf
'Address use IS_Isf
'Address;
102 for IV_Ifl
'Address use IS_Ifl
'Address;
103 for IV_Ilf
'Address use IS_Ilf
'Address;
104 for IV_Ill
'Address use IS_Ill
'Address;
106 -- The following pragmas are used to suppress initialization
108 pragma Import
(Ada
, IV_Isf
);
109 pragma Import
(Ada
, IV_Ifl
);
110 pragma Import
(Ada
, IV_Ilf
);
111 pragma Import
(Ada
, IV_Ill
);
114 -- Acquire environment variable value if necessary
116 if C1
= 'E' and then C2
= 'V' then
118 (EV_Val
'Address, Env_Value_Length
'Address, Env_Value_Ptr
'Address);
120 -- Ignore if length is not 2
122 if Env_Value_Length
/= 2 then
126 -- Length is 2, see if it is a valid value
129 -- Acquire two characters and fold to upper case
131 C1
:= Env_Value_Ptr
(1);
132 C2
:= Env_Value_Ptr
(2);
134 if C1
in 'a' .. 'z' then
135 C1
:= Character'Val (Character'Pos (C1
) - 32);
138 if C2
in 'a' .. 'z' then
139 C2
:= Character'Val (Character'Pos (C2
) - 32);
142 -- IN/LO/HI are ok values
144 if (C1
= 'I' and then C2
= 'N')
146 (C1
= 'L' and then C2
= 'O')
148 (C1
= 'H' and then C2
= 'I')
152 -- Try for valid hex digits
154 elsif (C1
in '0' .. '9' or else C1
in 'A' .. 'Z')
156 (C2
in '0' .. '9' or else C2
in 'A' .. 'Z')
160 -- Otherwise environment value is bad, ignore and use IN (invalid)
169 -- IN (invalid value)
171 if C1
= 'I' and then C2
= 'N' then
174 IS_Is4
:= 16#
8000_0000#
;
175 IS_Is8
:= 16#
8000_0000_0000_0000#
;
179 IS_Iu4
:= 16#FFFF_FFFF#
;
180 IS_Iu8
:= 16#FFFF_FFFF_FFFF_FFFF#
;
184 IS_Iz4
:= 16#
0000_0000#
;
185 IS_Iz8
:= 16#
0000_0000_0000_0000#
;
188 IV_Isf
:= 16#FFFF_FF00#
;
189 IV_Ifl
:= 16#FFFF_FF00#
;
190 IV_Ilf
:= (0, 16#FF#
, 16#FF#
, 16#FF#
, 16#FF#
, 16#FF#
);
195 IV_Ilf
:= To_ByteLF
(IS_Iu8
);
199 IV_Ill
:= (0, 0, 0, 0, 0, 0, 0, 16#C0#
, 16#FF#
, 16#FF#
, 0, 0);
204 elsif C1
= 'L' and then C2
= 'O' then
207 IS_Is4
:= 16#
8000_0000#
;
208 IS_Is8
:= 16#
8000_0000_0000_0000#
;
212 IS_Iu4
:= 16#
0000_0000#
;
213 IS_Iu8
:= 16#
0000_0000_0000_0000#
;
217 IS_Iz4
:= 16#
0000_0000#
;
218 IS_Iz8
:= 16#
0000_0000_0000_0000#
;
221 IV_Isf
:= 16#
0000_0001#
;
222 IV_Ifl
:= 16#
0000_0001#
;
223 IV_Ilf
:= (1, 0, 0, 0, 0, 0);
226 IV_Isf
:= 16#FF80_0000#
;
227 IV_Ifl
:= 16#FF80_0000#
;
228 IV_Ilf
:= To_ByteLF
(16#FFF0_0000_0000_0000#
);
232 IV_Ill
:= (0, 0, 0, 0, 0, 0, 0, 16#
80#
, 16#FF#
, 16#FF#
, 0, 0);
237 elsif C1
= 'H' and then C2
= 'I' then
240 IS_Is4
:= 16#
7FFF_FFFF#
;
241 IS_Is8
:= 16#
7FFF_FFFF_FFFF_FFFF#
;
245 IS_Iu4
:= 16#FFFF_FFFF#
;
246 IS_Iu8
:= 16#FFFF_FFFF_FFFF_FFFF#
;
250 IS_Iz4
:= 16#FFFF_FFFF#
;
251 IS_Iz8
:= 16#FFFF_FFFF_FFFF_FFFF#
;
254 IV_Isf
:= 16#
7FFF_FFFF#
;
255 IV_Ifl
:= 16#
7FFF_FFFF#
;
256 IV_Ilf
:= (16#FF#
, 16#FF#
, 16#FF#
, 16#FF#
, 16#FF#
, 16#
7F#
);
259 IV_Isf
:= 16#
7F80_0000#
;
260 IV_Ifl
:= 16#
7F80_0000#
;
261 IV_Ilf
:= To_ByteLF
(16#
7FF0_0000_0000_0000#
);
265 IV_Ill
:= (0, 0, 0, 0, 0, 0, 0, 16#
80#
, 16#FF#
, 16#
7F#
, 0, 0);
271 -- Convert the two hex digits (we know they are valid here)
273 B
:= 16 * (Character'Pos (C1
)
274 - (if C1
in '0' .. '9'
275 then Character'Pos ('0')
276 else Character'Pos ('A') - 10))
277 + (Character'Pos (C2
)
278 - (if C2
in '0' .. '9'
279 then Character'Pos ('0')
280 else Character'Pos ('A') - 10));
282 -- Initialize data values from the hex value
285 IS_Is2
:= 2**8 * Byte2
(IS_Is1
) + Byte2
(IS_Is1
);
286 IS_Is4
:= 2**16 * Byte4
(IS_Is2
) + Byte4
(IS_Is2
);
287 IS_Is8
:= 2**32 * Byte8
(IS_Is4
) + Byte8
(IS_Is4
);
303 IV_Ill
:= (B
, B
, B
, B
, B
, B
);
305 IV_Ilf
:= To_ByteLF
(IS_Is8
);
309 IV_Ill
:= (B
, B
, B
, B
, B
, B
, B
, B
, B
, B
, B
, B
);
313 -- If no separate Long_Long_Float, then use Long_Float value as
314 -- Long_Long_Float initial value.
318 pragma Warnings
(Off
); -- why???
319 function To_ByteLLF
is
320 new Ada
.Unchecked_Conversion
(ByteLF
, ByteLLF
);
321 pragma Warnings
(On
);
323 IV_Ill
:= To_ByteLLF
(IV_Ilf
);
328 end System
.Scalar_Values
;