1107590Sobrien/* Definitions of target machine for GNU compiler, for IBM S/390
2107590Sobrien   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3107590Sobrien   Contributed by Hartmut Penner (hpenner@de.ibm.com) and
4107590Sobrien                  Ulrich Weigand (uweigand@de.ibm.com).
5107590Sobrien
6132718SkanThis file is part of GCC.
7107590Sobrien
8132718SkanGCC is free software; you can redistribute it and/or modify it under
9132718Skanthe terms of the GNU General Public License as published by the Free
10132718SkanSoftware Foundation; either version 2, or (at your option) any later
11132718Skanversion.
12107590Sobrien
13132718SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
14132718SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
15132718SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16132718Skanfor more details.
17107590Sobrien
18107590SobrienYou should have received a copy of the GNU General Public License
19132718Skanalong with GCC; see the file COPYING.  If not, write to the Free
20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21169689Skan02110-1301, USA.  */
22107590Sobrien
23169689Skan#ifdef L_fixunstfdi
24169689Skan
25169689Skan#define EXPD(fp)	   (((fp.l.i[0]) >> 16) & 0x7FFF)
26169689Skan#define EXPONENT_BIAS	   16383
27169689Skan#define MANTISSA_BITS      112
28169689Skan#define PRECISION          (MANTISSA_BITS + 1)
29169689Skan#define SIGNBIT		   0x80000000
30169689Skan#define SIGND(fp)	   ((fp.l.i[0]) & SIGNBIT)
31169689Skan#define MANTD_HIGH_LL(fp)  ((fp.ll[0] & HIGH_LL_FRAC_MASK) | HIGH_LL_UNIT_BIT)
32169689Skan#define MANTD_LOW_LL(fp)   (fp.ll[1])
33169689Skan#define FRACD_ZERO_P(fp)   (!fp.ll[1] && !(fp.ll[0] & HIGH_LL_FRAC_MASK))
34169689Skan#define HIGH_LL_FRAC_BITS  48
35169689Skan#define HIGH_LL_UNIT_BIT   ((UDItype_x)1 << HIGH_LL_FRAC_BITS)
36169689Skan#define HIGH_LL_FRAC_MASK  (HIGH_LL_UNIT_BIT - 1)
37169689Skan
38169689Skantypedef int DItype_x __attribute__ ((mode (DI)));
39169689Skantypedef unsigned int UDItype_x __attribute__ ((mode (DI)));
40169689Skantypedef int SItype_x __attribute__ ((mode (SI)));
41169689Skantypedef unsigned int USItype_x __attribute__ ((mode (SI)));
42169689Skan
43169689Skanunion double_long {
44169689Skan  long double d;
45169689Skan  struct {
46169689Skan      SItype_x i[4]; /* 32 bit parts: 0 upper ... 3 lowest */
47169689Skan    } l;
48169689Skan  UDItype_x ll[2];   /* 64 bit parts: 0 upper, 1 lower */
49169689Skan};
50169689Skan
51169689SkanUDItype_x __fixunstfdi (long double a1);
52169689Skan
53169689Skan/* convert double to unsigned int */
54169689SkanUDItype_x
55169689Skan__fixunstfdi (long double a1)
56169689Skan{
57169689Skan    register union double_long dl1;
58169689Skan    register int exp;
59169689Skan    register UDItype_x l;
60169689Skan
61169689Skan    dl1.d = a1;
62169689Skan
63169689Skan    /* +/- 0, denormalized, negative */
64169689Skan    if (!EXPD (dl1) || SIGND(dl1))
65169689Skan      return 0;
66169689Skan
67169689Skan    /* The exponent - considered the binary point at the right end of
68169689Skan       the mantissa.  */
69169689Skan    exp = EXPD (dl1) - EXPONENT_BIAS - MANTISSA_BITS;
70169689Skan
71169689Skan    /* number < 1: If the mantissa would need to be right-shifted more bits than
72169689Skan       its size (plus the implied one bit on the left) the result would be
73169689Skan       zero.  */
74169689Skan    if (exp <= -PRECISION)
75169689Skan      return 0;
76169689Skan
77169689Skan    /* NaN: All exponent bits set and a nonzero fraction.  */
78169689Skan    if ((EXPD(dl1) == 0x7fff) && !FRACD_ZERO_P (dl1))
79169689Skan      return 0x0ULL;
80169689Skan
81169689Skan    /* If the upper ll part of the mantissa isn't
82169689Skan       zeroed out after shifting the number would be to large.  */
83169689Skan    if (exp >= -HIGH_LL_FRAC_BITS)
84169689Skan      return 0xFFFFFFFFFFFFFFFFULL;
85169689Skan
86169689Skan    exp += HIGH_LL_FRAC_BITS + 1;
87169689Skan
88169689Skan    l = MANTD_LOW_LL (dl1) >> (HIGH_LL_FRAC_BITS + 1)
89169689Skan        | MANTD_HIGH_LL (dl1) << (64 - (HIGH_LL_FRAC_BITS + 1));
90169689Skan
91169689Skan    return l >> -exp;
92169689Skan}
93169689Skan#define __fixunstfdi ___fixunstfdi
94169689Skan#endif
95169689Skan#undef L_fixunstfdi
96169689Skan
97169689Skan#ifdef L_fixtfdi
98169689Skan#define EXPD(fp)	   (((fp.l.i[0]) >> 16) & 0x7FFF)
99169689Skan#define EXPONENT_BIAS	   16383
100169689Skan#define MANTISSA_BITS      112
101169689Skan#define PRECISION          (MANTISSA_BITS + 1)
102169689Skan#define SIGNBIT		   0x80000000
103169689Skan#define SIGND(fp)	   ((fp.l.i[0]) & SIGNBIT)
104169689Skan#define MANTD_HIGH_LL(fp)  ((fp.ll[0] & HIGH_LL_FRAC_MASK) | HIGH_LL_UNIT_BIT)
105169689Skan#define MANTD_LOW_LL(fp)   (fp.ll[1])
106169689Skan#define FRACD_ZERO_P(fp)   (!fp.ll[1] && !(fp.ll[0] & HIGH_LL_FRAC_MASK))
107169689Skan#define HIGH_LL_FRAC_BITS  48
108169689Skan#define HIGH_LL_UNIT_BIT   ((UDItype_x)1 << HIGH_LL_FRAC_BITS)
109169689Skan#define HIGH_LL_FRAC_MASK  (HIGH_LL_UNIT_BIT - 1)
110169689Skan
111169689Skantypedef int DItype_x __attribute__ ((mode (DI)));
112169689Skantypedef unsigned int UDItype_x __attribute__ ((mode (DI)));
113169689Skantypedef int SItype_x __attribute__ ((mode (SI)));
114169689Skantypedef unsigned int USItype_x __attribute__ ((mode (SI)));
115169689Skan
116169689Skanunion double_long {
117169689Skan  long double d;
118169689Skan  struct {
119169689Skan      SItype_x i[4]; /* 32 bit parts: 0 upper ... 3 lowest */
120169689Skan    } l;
121169689Skan  DItype_x ll[2];   /* 64 bit parts: 0 upper, 1 lower */
122169689Skan};
123169689Skan
124169689SkanDItype_x __fixtfdi (long double a1);
125169689Skan
126169689Skan/* convert double to unsigned int */
127169689SkanDItype_x
128169689Skan__fixtfdi (long double a1)
129169689Skan{
130169689Skan    register union double_long dl1;
131169689Skan    register int exp;
132169689Skan    register UDItype_x l;
133169689Skan
134169689Skan    dl1.d = a1;
135169689Skan
136169689Skan    /* +/- 0, denormalized */
137169689Skan    if (!EXPD (dl1))
138169689Skan      return 0;
139169689Skan
140169689Skan    /* The exponent - considered the binary point at the right end of
141169689Skan       the mantissa.  */
142169689Skan    exp = EXPD (dl1) - EXPONENT_BIAS - MANTISSA_BITS;
143169689Skan
144169689Skan    /* number < 1: If the mantissa would need to be right-shifted more bits than
145169689Skan       its size the result would be zero.  */
146169689Skan    if (exp <= -PRECISION)
147169689Skan      return 0;
148169689Skan
149169689Skan    /* NaN: All exponent bits set and a nonzero fraction.  */
150169689Skan    if ((EXPD(dl1) == 0x7fff) && !FRACD_ZERO_P (dl1))
151169689Skan      return 0x8000000000000000ULL;
152169689Skan
153169689Skan    /* If the upper ll part of the mantissa isn't
154169689Skan       zeroed out after shifting the number would be to large.  */
155169689Skan    if (exp >= -HIGH_LL_FRAC_BITS)
156169689Skan      {
157169689Skan	l = (long long)1 << 63; /* long int min */
158169689Skan	return SIGND (dl1) ? l : l - 1;
159169689Skan      }
160169689Skan
161169689Skan    /* The extra bit is needed for the sign bit.  */
162169689Skan    exp += HIGH_LL_FRAC_BITS + 1;
163169689Skan
164169689Skan    l = MANTD_LOW_LL (dl1) >> (HIGH_LL_FRAC_BITS + 1)
165169689Skan        | MANTD_HIGH_LL (dl1) << (64 - (HIGH_LL_FRAC_BITS + 1));
166169689Skan
167169689Skan    return SIGND (dl1) ? -(l >> -exp) : l >> -exp;
168169689Skan}
169169689Skan#define __fixtfdi ___fixtfdi
170169689Skan#endif
171169689Skan#undef L_fixtfdi
172169689Skan
173107590Sobrien#ifdef L_fixunsdfdi
174107590Sobrien#define EXPD(fp)	(((fp.l.upper) >> 20) & 0x7FF)
175107590Sobrien#define EXCESSD		1022
176107590Sobrien#define SIGNBIT		0x80000000
177107590Sobrien#define SIGND(fp)	((fp.l.upper) & SIGNBIT)
178107590Sobrien#define MANTD_LL(fp)	((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
179107590Sobrien#define FRACD_LL(fp)	(fp.ll & (HIDDEND_LL-1))
180107590Sobrien#define HIDDEND_LL	((UDItype_x)1 << 52)
181107590Sobrien
182107590Sobrientypedef int DItype_x __attribute__ ((mode (DI)));
183107590Sobrientypedef unsigned int UDItype_x __attribute__ ((mode (DI)));
184107590Sobrientypedef int SItype_x __attribute__ ((mode (SI)));
185107590Sobrientypedef unsigned int USItype_x __attribute__ ((mode (SI)));
186107590Sobrien
187107590Sobrienunion double_long {
188107590Sobrien    double d;
189107590Sobrien    struct {
190107590Sobrien      SItype_x upper;
191107590Sobrien      USItype_x lower;
192107590Sobrien    } l;
193107590Sobrien    UDItype_x ll;
194107590Sobrien};
195107590Sobrien
196117395SkanUDItype_x __fixunsdfdi (double a1);
197107590Sobrien
198107590Sobrien/* convert double to unsigned int */
199107590SobrienUDItype_x
200107590Sobrien__fixunsdfdi (double a1)
201107590Sobrien{
202107590Sobrien    register union double_long dl1;
203107590Sobrien    register int exp;
204107590Sobrien    register UDItype_x l;
205107590Sobrien
206107590Sobrien    dl1.d = a1;
207107590Sobrien
208169689Skan    /* +/- 0, denormalized, negative */
209107590Sobrien
210107590Sobrien    if (!EXPD (dl1) || SIGND(dl1))
211107590Sobrien      return 0;
212107590Sobrien
213107590Sobrien    exp = EXPD (dl1) - EXCESSD - 53;
214107590Sobrien
215107590Sobrien    /* number < 1 */
216107590Sobrien
217107590Sobrien    if (exp < -53)
218107590Sobrien      return 0;
219107590Sobrien
220107590Sobrien    /* NaN */
221107590Sobrien
222107590Sobrien    if ((EXPD(dl1) == 0x7ff) && (FRACD_LL(dl1) != 0)) /* NaN */
223107590Sobrien      return 0x0ULL;
224107590Sobrien
225107590Sobrien    /* Number big number & + inf */
226107590Sobrien
227107590Sobrien    if (exp >= 12) {
228107590Sobrien      return 0xFFFFFFFFFFFFFFFFULL;
229107590Sobrien    }
230107590Sobrien
231107590Sobrien    l = MANTD_LL(dl1);
232107590Sobrien
233107590Sobrien    /* shift down until exp < 12 or l = 0 */
234107590Sobrien    if (exp > 0)
235107590Sobrien      l <<= exp;
236107590Sobrien    else
237107590Sobrien      l >>= -exp;
238107590Sobrien
239107590Sobrien    return l;
240107590Sobrien}
241107590Sobrien#define __fixunsdfdi ___fixunsdfdi
242107590Sobrien#endif
243107590Sobrien#undef L_fixunsdfdi
244107590Sobrien
245107590Sobrien#ifdef L_fixdfdi
246107590Sobrien#define EXPD(fp)	(((fp.l.upper) >> 20) & 0x7FF)
247107590Sobrien#define EXCESSD		1022
248107590Sobrien#define SIGNBIT		0x80000000
249107590Sobrien#define SIGND(fp)	((fp.l.upper) & SIGNBIT)
250107590Sobrien#define MANTD_LL(fp)	((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
251107590Sobrien#define FRACD_LL(fp)	(fp.ll & (HIDDEND_LL-1))
252107590Sobrien#define HIDDEND_LL	((UDItype_x)1 << 52)
253107590Sobrien
254107590Sobrientypedef int DItype_x __attribute__ ((mode (DI)));
255107590Sobrientypedef unsigned int UDItype_x __attribute__ ((mode (DI)));
256107590Sobrientypedef int SItype_x __attribute__ ((mode (SI)));
257107590Sobrientypedef unsigned int USItype_x __attribute__ ((mode (SI)));
258107590Sobrien
259107590Sobrienunion double_long {
260107590Sobrien    double d;
261107590Sobrien    struct {
262107590Sobrien      SItype_x upper;
263107590Sobrien      USItype_x lower;
264107590Sobrien    } l;
265107590Sobrien    UDItype_x ll;
266107590Sobrien};
267107590Sobrien
268117395SkanDItype_x __fixdfdi (double a1);
269117395Skan
270107590Sobrien/* convert double to int */
271107590SobrienDItype_x
272107590Sobrien__fixdfdi (double a1)
273107590Sobrien{
274107590Sobrien    register union double_long dl1;
275107590Sobrien    register int exp;
276107590Sobrien    register DItype_x l;
277107590Sobrien
278107590Sobrien    dl1.d = a1;
279107590Sobrien
280107590Sobrien    /* +/- 0, denormalized */
281107590Sobrien
282107590Sobrien    if (!EXPD (dl1))
283107590Sobrien      return 0;
284107590Sobrien
285107590Sobrien    exp = EXPD (dl1) - EXCESSD - 53;
286107590Sobrien
287107590Sobrien    /* number < 1 */
288107590Sobrien
289107590Sobrien    if (exp < -53)
290107590Sobrien      return 0;
291107590Sobrien
292107590Sobrien    /* NaN */
293107590Sobrien
294107590Sobrien    if ((EXPD(dl1) == 0x7ff) && (FRACD_LL(dl1) != 0)) /* NaN */
295107590Sobrien      return 0x8000000000000000ULL;
296107590Sobrien
297107590Sobrien    /* Number big number & +/- inf */
298107590Sobrien
299107590Sobrien    if (exp >= 11) {
300107590Sobrien	l = (long long)1<<63;
301107590Sobrien	if (!SIGND(dl1))
302107590Sobrien	    l--;
303107590Sobrien	return l;
304107590Sobrien    }
305107590Sobrien
306107590Sobrien    l = MANTD_LL(dl1);
307107590Sobrien
308107590Sobrien    /* shift down until exp < 12 or l = 0 */
309107590Sobrien    if (exp > 0)
310107590Sobrien      l <<= exp;
311107590Sobrien    else
312107590Sobrien      l >>= -exp;
313107590Sobrien
314107590Sobrien    return (SIGND (dl1) ? -l : l);
315107590Sobrien}
316107590Sobrien#define __fixdfdi ___fixdfdi
317107590Sobrien#endif
318107590Sobrien#undef L_fixdfdi
319107590Sobrien
320107590Sobrien#ifdef L_fixunssfdi
321107590Sobrien#define EXP(fp)         (((fp.l) >> 23) & 0xFF)
322107590Sobrien#define EXCESS          126
323107590Sobrien#define SIGNBIT         0x80000000
324107590Sobrien#define SIGN(fp)        ((fp.l) & SIGNBIT)
325107590Sobrien#define HIDDEN          (1 << 23)
326107590Sobrien#define MANT(fp)        (((fp.l) & 0x7FFFFF) | HIDDEN)
327107590Sobrien#define FRAC(fp)        ((fp.l) & 0x7FFFFF)
328107590Sobrien
329107590Sobrientypedef int DItype_x __attribute__ ((mode (DI)));
330107590Sobrientypedef unsigned int UDItype_x __attribute__ ((mode (DI)));
331107590Sobrientypedef int SItype_x __attribute__ ((mode (SI)));
332107590Sobrientypedef unsigned int USItype_x __attribute__ ((mode (SI)));
333107590Sobrien
334107590Sobrienunion float_long
335107590Sobrien  {
336107590Sobrien    float f;
337107590Sobrien    USItype_x l;
338107590Sobrien  };
339107590Sobrien
340117395SkanUDItype_x __fixunssfdi (float a1);
341117395Skan
342107590Sobrien/* convert float to unsigned int */
343107590SobrienUDItype_x
344107590Sobrien__fixunssfdi (float a1)
345107590Sobrien{
346107590Sobrien    register union float_long fl1;
347107590Sobrien    register int exp;
348107590Sobrien    register UDItype_x l;
349107590Sobrien
350107590Sobrien    fl1.f = a1;
351107590Sobrien
352169689Skan    /* +/- 0, denormalized, negative */
353107590Sobrien
354107590Sobrien    if (!EXP (fl1) || SIGN(fl1))
355107590Sobrien      return 0;
356107590Sobrien
357107590Sobrien    exp = EXP (fl1) - EXCESS - 24;
358107590Sobrien
359107590Sobrien    /* number < 1 */
360107590Sobrien
361107590Sobrien    if (exp < -24)
362107590Sobrien      return 0;
363107590Sobrien
364107590Sobrien    /* NaN */
365107590Sobrien
366107590Sobrien    if ((EXP(fl1) == 0xff) && (FRAC(fl1) != 0)) /* NaN */
367107590Sobrien      return 0x0ULL;
368107590Sobrien
369107590Sobrien    /* Number big number & + inf */
370107590Sobrien
371107590Sobrien    if (exp >= 41) {
372107590Sobrien      return 0xFFFFFFFFFFFFFFFFULL;
373107590Sobrien    }
374107590Sobrien
375107590Sobrien    l = MANT(fl1);
376107590Sobrien
377107590Sobrien    if (exp > 0)
378107590Sobrien      l <<= exp;
379107590Sobrien    else
380107590Sobrien      l >>= -exp;
381107590Sobrien
382107590Sobrien    return l;
383107590Sobrien}
384107590Sobrien#define __fixunssfdi ___fixunssfdi
385107590Sobrien#endif
386107590Sobrien#undef L_fixunssfdi
387107590Sobrien
388107590Sobrien#ifdef L_fixsfdi
389107590Sobrien#define EXP(fp)         (((fp.l) >> 23) & 0xFF)
390107590Sobrien#define EXCESS          126
391107590Sobrien#define SIGNBIT         0x80000000
392107590Sobrien#define SIGN(fp)        ((fp.l) & SIGNBIT)
393107590Sobrien#define HIDDEN          (1 << 23)
394107590Sobrien#define MANT(fp)        (((fp.l) & 0x7FFFFF) | HIDDEN)
395107590Sobrien#define FRAC(fp)        ((fp.l) & 0x7FFFFF)
396107590Sobrien
397107590Sobrientypedef int DItype_x __attribute__ ((mode (DI)));
398107590Sobrientypedef unsigned int UDItype_x __attribute__ ((mode (DI)));
399107590Sobrientypedef int SItype_x __attribute__ ((mode (SI)));
400107590Sobrientypedef unsigned int USItype_x __attribute__ ((mode (SI)));
401107590Sobrien
402107590Sobrienunion float_long
403107590Sobrien  {
404107590Sobrien    float f;
405107590Sobrien    USItype_x l;
406107590Sobrien  };
407107590Sobrien
408117395SkanDItype_x __fixsfdi (float a1);
409117395Skan
410107590Sobrien/* convert double to int */
411107590SobrienDItype_x
412107590Sobrien__fixsfdi (float a1)
413107590Sobrien{
414107590Sobrien    register union float_long fl1;
415107590Sobrien    register int exp;
416107590Sobrien    register DItype_x l;
417107590Sobrien
418107590Sobrien    fl1.f = a1;
419107590Sobrien
420107590Sobrien    /* +/- 0, denormalized */
421107590Sobrien
422107590Sobrien    if (!EXP (fl1))
423107590Sobrien      return 0;
424107590Sobrien
425107590Sobrien    exp = EXP (fl1) - EXCESS - 24;
426107590Sobrien
427107590Sobrien    /* number < 1 */
428107590Sobrien
429107590Sobrien    if (exp < -24)
430107590Sobrien      return 0;
431107590Sobrien
432107590Sobrien    /* NaN */
433107590Sobrien
434107590Sobrien    if ((EXP(fl1) == 0xff) && (FRAC(fl1) != 0)) /* NaN */
435107590Sobrien      return 0x8000000000000000ULL;
436107590Sobrien
437107590Sobrien    /* Number big number & +/- inf */
438107590Sobrien
439107590Sobrien    if (exp >= 40) {
440107590Sobrien	l = (long long)1<<63;
441107590Sobrien	if (!SIGN(fl1))
442107590Sobrien	    l--;
443107590Sobrien	return l;
444107590Sobrien    }
445107590Sobrien
446107590Sobrien    l = MANT(fl1);
447107590Sobrien
448107590Sobrien    if (exp > 0)
449107590Sobrien      l <<= exp;
450107590Sobrien    else
451107590Sobrien      l >>= -exp;
452107590Sobrien
453107590Sobrien    return (SIGN (fl1) ? -l : l);
454107590Sobrien}
455107590Sobrien#define __fixsfdi ___fixsfdi
456107590Sobrien#endif
457107590Sobrien#undef L_fixsfdi
458