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