2005-12-29 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / ada / s-scaval.adb
blob71b5c6017a59f2130a7d3d4a52ea412d13296f36
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUN-TIME COMPONENTS --
4 -- --
5 -- S Y S T E M . S C A L A R _ V A L U E S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2003-2005, 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 2, 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
21 -- --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
28 -- --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
31 -- --
32 ------------------------------------------------------------------------------
34 with Unchecked_Conversion;
36 package body System.Scalar_Values is
38 ----------------
39 -- Initialize --
40 ----------------
42 procedure Initialize (Mode1 : Character; Mode2 : Character) is
43 C1 : Character := Mode1;
44 C2 : Character := Mode2;
46 procedure Get_Env_Value_Ptr (Name, Length, Ptr : Address);
47 pragma Import (C, Get_Env_Value_Ptr, "__gnat_get_env_value_ptr");
49 subtype String2 is String (1 .. 2);
50 type String2_Ptr is access all String2;
52 Env_Value_Ptr : aliased String2_Ptr;
53 Env_Value_Length : aliased Integer;
55 EV_Val : aliased constant String :=
56 "GNAT_INIT_SCALARS" & ASCII.NUL;
58 B : Byte1;
60 EFloat : constant Boolean := Long_Long_Float'Size > Long_Float'Size;
61 -- Set True if we are on an x86 with 96-bit floats for extended
63 type ByteLF is array (0 .. 7 + 4 * Boolean'Pos (EFloat)) of Byte1;
64 -- Type used to initialize Long_Long_Float values used on x86 and
65 -- any other target with the same 80-bit floating-point values that
66 -- GCC always stores in 96-bits. Note that we are assuming Intel
67 -- format little-endian addressing for this type. On non-Intel
68 -- architectures, this is the same length as Byte8 and holds
69 -- a Long_Float value.
71 -- The following variables are used to initialize the float values
72 -- by overlay. We can't assign directly to the float values, since
73 -- we may be assigning signalling Nan's that will cause a trap if
74 -- loaded into a floating-point register.
76 IV_Isf : aliased Byte4; -- Initialize short float
77 IV_Ifl : aliased Byte4; -- Initialize float
78 IV_Ilf : aliased Byte8; -- Initialize long float
79 IV_Ill : aliased ByteLF; -- Initialize long long float
81 for IV_Isf'Address use IS_Isf'Address;
82 for IV_Ifl'Address use IS_Ifl'Address;
83 for IV_Ilf'Address use IS_Ilf'Address;
84 for IV_Ill'Address use IS_Ill'Address;
86 -- The following pragmas are used to suppress initialization
88 pragma Import (Ada, IV_Isf);
89 pragma Import (Ada, IV_Ifl);
90 pragma Import (Ada, IV_Ilf);
91 pragma Import (Ada, IV_Ill);
93 begin
94 -- Acquire environment variable value if necessary
96 if C1 = 'E' and then C2 = 'V' then
97 Get_Env_Value_Ptr
98 (EV_Val'Address, Env_Value_Length'Address, Env_Value_Ptr'Address);
100 -- Ignore if length is not 2
102 if Env_Value_Length /= 2 then
103 C1 := 'I';
104 C2 := 'N';
106 -- Length is 2, see if it is a valid value
108 else
109 -- Acquire two characters and fold to upper case
111 C1 := Env_Value_Ptr (1);
112 C2 := Env_Value_Ptr (2);
114 if C1 in 'a' .. 'z' then
115 C1 := Character'Val (Character'Pos (C1) - 32);
116 end if;
118 if C2 in 'a' .. 'z' then
119 C2 := Character'Val (Character'Pos (C2) - 32);
120 end if;
122 -- IN/LO/HI are ok values
124 if (C1 = 'I' and then C2 = 'N')
125 or else
126 (C1 = 'L' and then C2 = 'O')
127 or else
128 (C1 = 'H' and then C2 = 'I')
129 then
130 null;
132 -- Try for valid hex digits
134 elsif (C1 in '0' .. '9' or else C1 in 'A' .. 'Z')
135 or else
136 (C2 in '0' .. '9' or else C2 in 'A' .. 'Z')
137 then
138 null;
140 -- Otherwise environment value is bad, ignore and use IN (invalid)
142 else
143 C1 := 'I';
144 C2 := 'N';
145 end if;
146 end if;
147 end if;
149 -- IN (invalid value)
151 if C1 = 'I' and then C2 = 'N' then
152 IS_Is1 := 16#80#;
153 IS_Is2 := 16#8000#;
154 IS_Is4 := 16#8000_0000#;
155 IS_Is8 := 16#8000_0000_0000_0000#;
157 IS_Iu1 := 16#FF#;
158 IS_Iu2 := 16#FFFF#;
159 IS_Iu4 := 16#FFFF_FFFF#;
160 IS_Iu8 := 16#FFFF_FFFF_FFFF_FFFF#;
162 IS_Iz1 := 16#00#;
163 IS_Iz2 := 16#0000#;
164 IS_Iz4 := 16#0000_0000#;
165 IS_Iz8 := 16#0000_0000_0000_0000#;
167 IV_Isf := IS_Iu4;
168 IV_Ifl := IS_Iu4;
169 IV_Ilf := IS_Iu8;
171 if EFloat then
172 IV_Ill := (0, 0, 0, 0, 0, 0, 0, 16#C0#, 16#FF#, 16#FF#, 0, 0);
173 end if;
175 -- LO (Low values)
177 elsif C1 = 'L' and then C2 = 'O' then
178 IS_Is1 := 16#80#;
179 IS_Is2 := 16#8000#;
180 IS_Is4 := 16#8000_0000#;
181 IS_Is8 := 16#8000_0000_0000_0000#;
183 IS_Iu1 := 16#00#;
184 IS_Iu2 := 16#0000#;
185 IS_Iu4 := 16#0000_0000#;
186 IS_Iu8 := 16#0000_0000_0000_0000#;
188 IS_Iz1 := 16#00#;
189 IS_Iz2 := 16#0000#;
190 IS_Iz4 := 16#0000_0000#;
191 IS_Iz8 := 16#0000_0000_0000_0000#;
193 IV_Isf := 16#FF80_0000#;
194 IV_Ifl := 16#FF80_0000#;
195 IV_Ilf := 16#FFF0_0000_0000_0000#;
197 if EFloat then
198 IV_Ill := (0, 0, 0, 0, 0, 0, 0, 16#80#, 16#FF#, 16#FF#, 0, 0);
199 end if;
201 -- HI (High values)
203 elsif C1 = 'H' and then C2 = 'I' then
204 IS_Is1 := 16#7F#;
205 IS_Is2 := 16#7FFF#;
206 IS_Is4 := 16#7FFF_FFFF#;
207 IS_Is8 := 16#7FFF_FFFF_FFFF_FFFF#;
209 IS_Iu1 := 16#FF#;
210 IS_Iu2 := 16#FFFF#;
211 IS_Iu4 := 16#FFFF_FFFF#;
212 IS_Iu8 := 16#FFFF_FFFF_FFFF_FFFF#;
214 IS_Iz1 := 16#FF#;
215 IS_Iz2 := 16#FFFF#;
216 IS_Iz4 := 16#FFFF_FFFF#;
217 IS_Iz8 := 16#FFFF_FFFF_FFFF_FFFF#;
219 IV_Isf := 16#7F80_0000#;
220 IV_Ifl := 16#7F80_0000#;
221 IV_Ilf := 16#7FF0_0000_0000_0000#;
223 if EFloat then
224 IV_Ill := (0, 0, 0, 0, 0, 0, 0, 16#80#, 16#FF#, 16#7F#, 0, 0);
225 end if;
227 -- -Shh (hex byte)
229 else
230 -- Convert the two hex digits (we know they are valid here)
232 if C1 in '0' .. '9' then
233 B := Character'Pos (C1) - Character'Pos ('0');
234 else
235 B := Character'Pos (C1) - (Character'Pos ('A') - 10);
236 end if;
238 if C2 in '0' .. '9' then
239 B := B * 16 + Character'Pos (C2) - Character'Pos ('0');
240 else
241 B := B * 16 + Character'Pos (C2) - (Character'Pos ('A') - 10);
242 end if;
244 -- Initialize data values from the hex value
246 IS_Is1 := B;
247 IS_Is2 := 2**8 * Byte2 (IS_Is1) + Byte2 (IS_Is1);
248 IS_Is4 := 2**16 * Byte4 (IS_Is2) + Byte4 (IS_Is2);
249 IS_Is8 := 2**32 * Byte8 (IS_Is4) + Byte8 (IS_Is4);
251 IS_Iu1 := IS_Is1;
252 IS_Iu2 := IS_Is2;
253 IS_Iu4 := IS_Is4;
254 IS_Iu8 := IS_Is8;
256 IS_Iz1 := IS_Is1;
257 IS_Iz2 := IS_Is2;
258 IS_Iz4 := IS_Is4;
259 IS_Iz8 := IS_Is8;
261 IV_Isf := IS_Is4;
262 IV_Ifl := IS_Is4;
263 IV_Ilf := IS_Is8;
265 if EFloat then
266 IV_Ill := (B, B, B, B, B, B, B, B, B, B, B, B);
267 end if;
268 end if;
270 -- If no separate Long_Long_Float, then use Long_Float value as
271 -- Long_Long_Float initial value.
273 if not EFloat then
274 declare
275 pragma Warnings (Off);
276 function To_ByteLF is new Unchecked_Conversion (Byte8, ByteLF);
277 pragma Warnings (On);
278 begin
279 IV_Ill := To_ByteLF (IV_Ilf);
280 end;
281 end if;
282 end Initialize;
284 end System.Scalar_Values;