/* Definitions for SMAP II BCD support in the GNU C Compiler. These macros implement software BCD floating point support; primary use will be TIGCC. Copyright (C) 1994 Free Software Foundation, Inc. Copyright (C) 2000 Sebastian Reichelt Copyright (C) 2003-2005 Kevin Kofler This file is part of TIGCC. GNU CC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #undef TARGET_FLOAT_FORMAT #define TARGET_FLOAT_FORMAT SMAP_BCD_FLOAT_FORMAT #ifndef __SMAP_BCD_FLOAT #define __SMAP_BCD_FLOAT typedef struct real_value smap_bcd_float; #endif #undef REAL_VALUE_TYPE #define REAL_VALUE_TYPE smap_bcd_float #undef FLOAT_TYPE_SIZE #undef DOUBLE_TYPE_SIZE #undef LONG_DOUBLE_TYPE_SIZE /* We have to define a special mode for this; one that handles 10 byte floats. There have to be a lot of changes to other files; due to the fact that they are so countless, it would be too hard to make them compatible with a general-purpose GCC. */ #define FLOAT_TYPE_SIZE 80 #define DOUBLE_TYPE_SIZE 80 #define LONG_DOUBLE_TYPE_SIZE 80 #ifndef REAL_IS_NOT_DOUBLE #define REAL_IS_NOT_DOUBLE #endif #define ZERO (__extension__(smap_bcd_float){0x4000,0}) #define UNSIGNED_ZERO (__extension__(smap_bcd_float){0x4000,0}) #define POSITIVE_ZERO (__extension__(smap_bcd_float){0,0}) #define NEGATIVE_ZERO (__extension__(smap_bcd_float){0x8000,0}) #define UNSIGNED_INF (__extension__(smap_bcd_float){0x7FFF,0xAA00CC0000000000ull}) #define POSITIVE_INF (__extension__(smap_bcd_float){0x7FFF,0xAA00BB0000000000ull}) #define NEGATIVE_INF (__extension__(smap_bcd_float){0xFFFF,0xAA00BB0000000000ull}) #define NAN (__extension__(smap_bcd_float){0x7FFF,0xAA00000000000000ull}) #ifndef REAL_INFINITY #define REAL_INFINITY #endif #undef REAL_VALUE_ISNAN #define REAL_VALUE_ISNAN(x) \ (REAL_VALUES_IDENTICAL (x, NAN)) #undef REAL_VALUE_ISINF #define REAL_VALUE_ISINF(x) \ ((REAL_VALUES_IDENTICAL (x, POSITIVE_INF)) \ || (REAL_VALUES_IDENTICAL (x, NEGATIVE_INF)) \ || (REAL_VALUES_IDENTICAL (x, UNSIGNED_INF))) #define REAL_VALUE_ISNANUINF(x) \ ((REAL_VALUE_ISNAN (x)) \ || (REAL_VALUES_IDENTICAL (x, UNSIGNED_INF))) #define REAL_VALUE_ISFINITE(x) \ (!(REAL_VALUE_ISNAN (x)) \ && !(REAL_VALUE_ISINF (x))) #define REAL_VALUE_ISZERO(x) \ (!((x).mantissa)) #undef REAL_VALUE_MINUS_ZERO #define REAL_VALUE_MINUS_ZERO(x) \ (REAL_VALUES_IDENTICAL (x, NEGATIVE_ZERO)) #define REAL_VALUE_ISPOSITIVE(x) \ (!(REAL_VALUE_ISNANUINF (x)) \ && ((x).exponent < 0x8000) \ && !(REAL_VALUE_ISZERO (x))) #define REAL_VALUE_ISNEGATIVE(x) \ (!(REAL_VALUE_ISNANUINF (x)) \ && ((x).exponent >= 0x8000) \ && !(REAL_VALUE_ISZERO (x))) #undef REAL_VALUE_POSITIVE #define REAL_VALUE_POSITIVE(x) \ (REAL_VALUE_ISPOSITIVE (x)) #undef REAL_VALUE_NEGATIVE #define REAL_VALUE_NEGATIVE(x) \ (REAL_VALUE_ISNEGATIVE (x)) #define real_isneg(x) \ (REAL_VALUE_ISNEGATIVE (*(x))) #undef REAL_VALUES_IDENTICAL #define REAL_VALUES_IDENTICAL(x, y) \ ((x).exponent == (y).exponent && (x).mantissa == (y).mantissa) #undef REAL_VALUES_EQUAL #define REAL_VALUES_EQUAL(x,y) \ (((REAL_VALUES_IDENTICAL (x, y)) \ && !REAL_VALUE_ISNANUINF (x) \ && !REAL_VALUE_ISNANUINF (y)) \ || (REAL_VALUE_ISZERO (x) \ && REAL_VALUE_ISZERO (y))) #undef REAL_VALUES_LESS #define REAL_VALUES_LESS(x,y) \ __extension__ ({ \ register int result = 0; \ if (REAL_VALUE_ISNANUINF (x) \ || REAL_VALUE_ISNANUINF (y) \ || REAL_VALUES_EQUAL (x, y) \ || (REAL_VALUE_ISPOSITIVE (x) && !(REAL_VALUE_ISPOSITIVE (y))) \ || (!(REAL_VALUE_ISNEGATIVE (x)) && REAL_VALUE_ISNEGATIVE (y))) \ result = 0; \ else if ((REAL_VALUE_ISNEGATIVE (x) && !(REAL_VALUE_ISNEGATIVE (y))) \ || (!(REAL_VALUE_ISPOSITIVE (x)) && REAL_VALUE_ISPOSITIVE (y))) \ result = 1; \ else \ { \ if ((x).exponent == (y).exponent) \ { \ if (REAL_VALUE_ISNEGATIVE (x)) \ result = ((x).mantissa > (y).mantissa); \ else \ result = ((x).mantissa < (y).mantissa); \ } \ else \ { \ if (REAL_VALUE_ISNEGATIVE (x)) \ result = ((x).exponent > (y).exponent); \ else \ result = ((x).exponent < (y).exponent); \ } \ } \ result; \ }) #undef REAL_VALUE_LDEXP #define REAL_VALUE_LDEXP(x,tempscale) \ __extension__ ({ \ REAL_VALUE_TYPE __tempx = x; \ int scale; \ unsigned long long pmul; \ signed short carry, help; \ if (REAL_VALUE_ISFINITE (__tempx)) \ { \ if (tempscale > 0) \ for (scale = 0; scale < tempscale; scale++) \ { \ if (__tempx.mantissa >= 0x5000000000000000ull) \ { \ __tempx.mantissa /= 0x10; \ __tempx.exponent++; \ } \ carry = 0; \ for (pmul = 1; 1; pmul *= 0x10) \ { \ help = (__tempx.mantissa / pmul) & 0xF; \ __tempx.mantissa -= ((unsigned long long) help) * pmul; \ help *= 2; \ help += carry; \ carry = help / 10; \ __tempx.mantissa += ((unsigned long long) (help % 10)) * pmul; \ if (pmul >= 0x1000000000000000ull) \ break; \ } \ } \ else if (tempscale < 0) \ for (scale = 0; scale > tempscale; scale--) \ { \ carry = 0; \ for (pmul = 0x1000000000000000ull; pmul > 0; pmul /= 0x10) \ { \ help = (__tempx.mantissa / pmul) & 0xF; \ __tempx.mantissa -= ((unsigned long long) help) * pmul; \ help += carry; \ __tempx.mantissa += ((unsigned long long) (help / 2)) * pmul; \ carry = (help % 2) * 10; \ } \ if (__tempx.mantissa < 0x1000000000000000ull) \ { \ __tempx.mantissa *= 0x10; \ __tempx.mantissa += carry / 2; \ __tempx.exponent--; \ } \ } \ } \ __tempx; \ }) #undef REAL_VALUE_FIX #define REAL_VALUE_FIX(x) \ ((REAL_VALUE_ISNEGATIVE (x)) \ ? (-(REAL_VALUE_UNSIGNED_FIX (REAL_VALUE_NEGATE (x)))) \ : (REAL_VALUE_UNSIGNED_FIX (x))) #undef REAL_VALUE_UNSIGNED_FIX #define REAL_VALUE_UNSIGNED_FIX(x) \ __extension__ ({ \ register unsigned int r = 0; \ signed char i; \ unsigned long long mpmul = 0x1000000000000000ull; \ if (((x.exponent & 0x7FFF) >= 0x4000) && ((x.exponent & 0x7FFF) < 0x4016)) \ { \ for (i = 0; i <= (x.exponent & 0x7FFF) - 0x4000; i++) \ if (mpmul) \ { \ r *= 10; \ r += (x.mantissa / mpmul) & 0xF; \ mpmul /= 0x10; \ } \ } \ r; \ }) #undef REAL_VALUE_RNDZINT #define REAL_VALUE_RNDZINT(x) \ __extension__ ({ \ REAL_VALUE_TYPE r = ZERO; \ signed char i; \ unsigned long long mpmul = 0x1000000000000000ull; \ r.exponent = (x).exponent; \ if (((r.exponent & 0x7FFF) >= 0x4000) && ((r.exponent & 0x7FFF) < 0x4016)) \ { \ for (i = 0; i <= (r.exponent & 0x7FFF) - 0x4000; i++) \ if (mpmul) \ { \ r.mantissa += x.mantissa & (0xF * mpmul); \ mpmul /= 0x10; \ } \ } \ r; \ }) #undef REAL_VALUE_UNSIGNED_RNDZINT #define REAL_VALUE_UNSIGNED_RNDZINT(x) \ ((REAL_VALUE_ISPOSITIVE (x)) \ ? (REAL_VALUE_RNDZINT (x)) \ : (ZERO)) #undef REAL_VALUE_ATOF #define REAL_VALUE_ATOF(string,mode) \ real_from_string2((string), (mode)) #undef REAL_ARITHMETIC #define REAL_ARITHMETIC(value, code, d1, d2) \ real_arithmetic (&(value), (code), &(d1), &(d2)) #undef REAL_VALUE_NEGATE #define REAL_VALUE_NEGATE(x) \ __extension__ ({ \ REAL_VALUE_TYPE __tempx = x; \ if ((!(REAL_VALUE_ISNANUINF (__tempx))) && ((__tempx.mantissa) || (__tempx.exponent != 0x4000))) \ __tempx.exponent ^= 0x8000; \ __tempx; \ }) #undef REAL_VALUE_TRUNCATE #define REAL_VALUE_TRUNCATE(mode,x) \ (x) #define real_convert(r,mode,x) \ (*(r)=*(x)) #define REAL_VALUE_TO_INT(lo, hi, r) real_to_integer2 ((lo), (hi), &(r)) #define REAL_VALUE_FROM_INT(d, lo, hi, mode) \ real_from_integer (&(d), (mode), (lo), (hi), 0) #define REAL_VALUE_FROM_UNSIGNED_INT(d, lo, hi, mode) \ real_from_integer (&(d), (mode), (lo), (hi), 1) #undef REAL_VALUE_TO_TARGET_SINGLE #define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \ gcc_unreachable(); #undef REAL_VALUE_TO_TARGET_DOUBLE #define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \ gcc_unreachable(); #undef REAL_VALUE_TO_TARGET_LONG_DOUBLE #define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) \ do { \ REAL_VALUE_TYPE f = (IN); \ (OUT)[0] = f.exponent * 0x10000 + ((unsigned short) (f.mantissa / 0x1000000000000ull)), (OUT)[1] = (unsigned long) (f.mantissa / 0x10000), (OUT)[2] = ((unsigned short) (f.mantissa)) * 0x10000; \ } while (0) #undef REAL_VALUE_TO_TARGET_SMAP_BCD #define REAL_VALUE_TO_TARGET_SMAP_BCD(IN, OUT) \ do { \ REAL_VALUE_TYPE f = (IN); \ (OUT)[0] = f.exponent, (OUT)[1] = (unsigned long) (f.mantissa / 0x100000000ull), (OUT)[2] = (unsigned long) (f.mantissa); \ } while (0) #define REAL_VALUE_TO_STRING(IN, OUT) \ do { \ REAL_VALUE_TYPE f = (IN); \ if (REAL_VALUE_ISNAN (f)) \ sprintf ((OUT), "NaN"); \ else if (REAL_VALUES_IDENTICAL (f, UNSIGNED_INF)) \ sprintf ((OUT), "Inf"); \ else if (REAL_VALUES_IDENTICAL (f, POSITIVE_INF)) \ sprintf ((OUT), "+Inf"); \ else if (REAL_VALUES_IDENTICAL (f, NEGATIVE_INF)) \ sprintf ((OUT), "-Inf"); \ else if (REAL_VALUES_IDENTICAL (f, UNSIGNED_ZERO)) \ sprintf ((OUT), "0.0"); \ else if (REAL_VALUES_IDENTICAL (f, POSITIVE_ZERO)) \ sprintf ((OUT), "+0.0"); \ else if (REAL_VALUES_IDENTICAL (f, NEGATIVE_ZERO)) \ sprintf ((OUT), "-0.0"); \ else \ { \ long exp; \ int neg = REAL_VALUE_ISNEGATIVE (f); \ if (neg) \ exp = f.exponent - 0xC000; \ else \ exp = f.exponent - 0x4000; \ sprintf ((OUT), "%s%lx.%07lx%08lxe%d", neg ? "-" : "", (unsigned long) (f.mantissa >> 60), (unsigned long) (f.mantissa >> 32) & 0x0ffffffful, (unsigned long) (f.mantissa), (int) (exp)); \ } \ } while (0) #define REAL_VALUE_ABS(x) ((REAL_VALUE_ISNEGATIVE((x))\ || REAL_VALUE_MINUS_ZERO((x))\ || REAL_VALUES_IDENTICAL ((x), NEGATIVE_INF))?\ REAL_VALUE_NEGATE((x)):(x)) /* WARNING: This is the number of bits we can represent, not the true size of the mantissa. */ #define significand_size(dummy) (53) #undef MODE_HAS_NANS #define MODE_HAS_NANS(MODE) ((MODE)==BFmode) #undef MODE_HAS_INFINITIES #define MODE_HAS_INFINITIES(MODE) ((MODE)==BFmode) /* FIXME: GCC expects this to mean that there is only 0 and -0. We actually have 0, +0 and -0. This allows a few optimizations GCC is too cautious to do in the presence of signed zeros. */ #undef MODE_HAS_SIGNED_ZEROS #define MODE_HAS_SIGNED_ZEROS(MODE) ((MODE)==BFmode) #define REAL_MODE_FORMAT_COMPOSITE_P(dummy) (0) /* end of smapbcd.h */