X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftv%2Ffltcalc.c;h=bc9d803bd1bf9d2a13b7fe372cf0e879e8828d81;hb=2d09549421b49587d4680a94dab277646e9fef44;hp=60556050c38557e2cf915c9337840dd989ef08e8;hpb=86b5e05a8b444327d8d464453146043fd3b93f76;p=libfirm diff --git a/ir/tv/fltcalc.c b/ir/tv/fltcalc.c index 60556050c..bc9d803bd 100644 --- a/ir/tv/fltcalc.c +++ b/ir/tv/fltcalc.c @@ -1,7 +1,21 @@ -/* fltcalc.c - * Authors: Matthias Heil +/* + * Project: libFIRM + * File name: ir/tv/fltcalc.c + * Purpose: + * Author: + * Modified by: + * Created: 2003 + * CVS-ID: $Id$ + * Copyright: (c) 2003 Universität Karlsruhe + * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + #include "fltcalc.h" #include "strcalc.h" @@ -11,56 +25,57 @@ # undef NAN #endif +#ifdef HAVE_INTTYPES_H #include +#endif + #include #include #include #include -#include - -typedef uint32_t UINT32; -#ifdef WORD_LITTLE_ENDIAN -#undef WORD_LITTLE_ENDIAN +#ifdef HAVE_ALLOCA_H +# include #endif -#ifdef WORD_BIG_ENDIAN -#undef WORD_BIG_ENDIAN +#ifdef HAVE_MALLOC_H +# include #endif -#define WORD_LITTLE_ENDIAN + +typedef uint32_t UINT32; #ifdef HAVE_LONG_DOUBLE -#ifdef WORD_LITTLE_ENDIAN +#ifdef WORDS_BIGENDIAN typedef union { struct { - UINT32 low; - UINT32 mid; UINT32 high; + UINT32 mid; + UINT32 low; } val; volatile long double d; } value_t; #else typedef union { struct { - UINT32 high; - UINT32 mid; UINT32 low; + UINT32 mid; + UINT32 high; } val; volatile long double d; } value_t; #endif #else -#ifdef WORD_LITTLE_ENDIAN +#ifdef WORDS_BIGENDIAN typedef union { struct { - UINT32 low; UINT32 high; + UINT32 low; } val; volatile double d; } value_t; #else typedef union { struct { - UINT32 high; UINT32 low; + UINT32 high; } val; volatile double d; } value_t; @@ -91,7 +106,7 @@ typedef struct { * value is represented as a pseudo-struct char array, addressed * by macros * struct { - * char sign; // 0 for positive, 1 for negative + * char sign; // 0 for positive, 1 for negative * char exp[VALUE_SIZE]; * char mant[VALUE_SIZE]; * descriptor_t desc; @@ -159,7 +174,7 @@ static void _fail_char(const char *str, unsigned int len, int pos) } #endif -/* pack ieee-like */ +/* pack machine-like */ static char* _pack(const char *int_float, char *packed) { char *shift_val; @@ -240,7 +255,7 @@ char* _normalize(const char *in_val, char *out_val, int sticky) hsb = -1; } - /* shift the first 1 ito the left of the radix point (i.e. hsb == -1) */ + /* shift the first 1 into the left of the radix point (i.e. hsb == -1) */ if (hsb < -1) { /* shift right */ @@ -428,7 +443,6 @@ static char* _add(const char* a, const char* b, char* result) /* determine if this is an addition or subtraction */ sign = _sign(a) ^ _sign(b); - DEBUGPRINTF(("sign a: %d, sign b: %d -> %s\n", _sign(a), _sign(b), sign?"sub":"add")); /* produce nan on inf - inf */ if (sign && (_desc(a).class == INF) && (_desc(b).class == INF)) @@ -802,19 +816,19 @@ char* _calc(const char *a, const char *b, int opcode, char *result) if (result == NULL) result = calc_buffer; - TRACEPRINTF(("%s ", fc_print(a, buffer, 100, FC_HEX))); + TRACEPRINTF(("%s ", fc_print(a, buffer, 100, FC_PACKED))); switch (opcode) { case FC_add: /* make the value with the bigger exponent the first one */ - TRACEPRINTF(("+ %s ", fc_print(b, buffer, 100, FC_HEX))); + TRACEPRINTF(("+ %s ", fc_print(b, buffer, 100, FC_PACKED))); if (sc_comp(_exp(a), _exp(b)) == -1) _add(b, a, result); else _add(a, b, result); break; case FC_sub: - TRACEPRINTF(("- %s ", fc_print(b, buffer, 100, FC_HEX))); + TRACEPRINTF(("- %s ", fc_print(b, buffer, 100, FC_PACKED))); temp = alloca(CALC_BUFFER_SIZE); memcpy(temp, b, CALC_BUFFER_SIZE); _sign(temp) = !_sign(b); @@ -824,11 +838,11 @@ char* _calc(const char *a, const char *b, int opcode, char *result) _add(a, temp, result); break; case FC_mul: - TRACEPRINTF(("* %s ", fc_print(b, buffer, 100, FC_HEX))); + TRACEPRINTF(("* %s ", fc_print(b, buffer, 100, FC_PACKED))); _mul(a, b, result); break; case FC_div: - TRACEPRINTF(("/ %s ", fc_print(b, buffer, 100, FC_HEX))); + TRACEPRINTF(("/ %s ", fc_print(b, buffer, 100, FC_PACKED))); _div(a, b, result); break; case FC_neg: @@ -843,7 +857,7 @@ char* _calc(const char *a, const char *b, int opcode, char *result) break; } - TRACEPRINTF(("= %s\n", fc_print(result, buffer, 100, FC_HEX))); + TRACEPRINTF(("= %s\n", fc_print(result, buffer, 100, FC_PACKED))); return result; } @@ -1017,7 +1031,7 @@ char* fc_val_from_str(const char *str, unsigned int len, char exp_size, char man _fail_char(old_str, len, str - old_str); } } - } // switch(state) + } /* switch(state) */ done: sc_val_from_str(mant_str, strlen(mant_str), _mant(result)); @@ -1058,34 +1072,34 @@ done: char* fc_val_from_float(LLDBL l, char exp_size, char mant_size, char* result) { char *temp; - int bias_res = ((1<> 16; - UINT32 mantissa1 = srcval.val.mid; - UINT32 mantissa0 = srcval.val.low; + mant_val = 64; + bias_val = 0x3fff; + sign = (srcval.val.high & 0x00008000) != 0; + exponent = (srcval.val.high & 0x00007FFF) ; + mantissa0 = srcval.val.mid; + mantissa1 = srcval.val.low; #else /* no long double */ - mant_val = 52; - bias_val = 0x3ff; - UINT32 sign = (srcval.val.high & 0x80000000) != 0; - UINT32 exponent = (srcval.val.high & 0x7FF00000) >> 20; - UINT32 mantissa0 = srcval.val.high & 0x000FFFFF; - UINT32 mantissa1 = srcval.val.low; + mant_val = 52; + bias_val = 0x3ff; + sign = (srcval.val.high & 0x80000000) != 0; + exponent = (srcval.val.high & 0x7FF00000) >> 20; + mantissa0 = srcval.val.high & 0x000FFFFF; + mantissa1 = srcval.val.low; #endif #ifdef HAVE_LONG_DOUBLE - TRACEPRINTF(("val_from_float(%.8X%.8X%.8X)\n", ((int*)&l)[2], ((int*)&l)[1], ((int*)&l)[0])); + TRACEPRINTF(("val_from_float(%.8X%.8X%.8X)\n", ((int*)&l)[2], ((int*)&l)[1], ((int*)&l)[0]));/* srcval.val.high, srcval.val.mid, srcval.val.low)); */ DEBUGPRINTF(("(%d-%.4X-%.8X%.8X)\n", sign, exponent, mantissa0, mantissa1)); #else - TRACEPRINTF(("val_from_float(%.8X%.8X)\n", ((int*)&l)[1], ((int*)&l)[0])); + TRACEPRINTF(("val_from_float(%.8X%.8X)\n", srcval.val.high, srcval.val.low)); DEBUGPRINTF(("(%d-%.3X-%.5X%.8X)\n", sign, exponent, mantissa0, mantissa1)); #endif @@ -1111,10 +1125,18 @@ char* fc_val_from_float(LLDBL l, char exp_size, char mant_size, char* result) return result; } - /* extract exponent */ + /* build exponent, because input and output exponent and mantissa sizes may differ + * this looks more complicated than it is: unbiased input exponent + output bias, + * minus the mantissa difference which is added again later when the output float + * becomes normalized */ +#ifdef HAVE_EXPLICIT_ONE + sc_val_from_long((exponent-bias_val+bias_res)-(mant_val-mant_size-1), _exp(result)); +#else sc_val_from_long((exponent-bias_val+bias_res)-(mant_val-mant_size), _exp(result)); +#endif - /* extract mantissa */ + /* build mantissa representation */ +#ifndef HAVE_EXPLICIT_ONE if (exponent != 0) { /* insert the hidden bit */ @@ -1123,6 +1145,7 @@ char* fc_val_from_float(LLDBL l, char exp_size, char mant_size, char* result) _shift_left(temp, sc_get_buffer(), NULL); } else +#endif { sc_val_from_ulong(0, NULL); } @@ -1151,7 +1174,7 @@ char* fc_val_from_float(LLDBL l, char exp_size, char mant_size, char* result) _normalize(result, result, 0); - TRACEPRINTF(("val_from_float results in %s\n", fc_print(result, temp, CALC_BUFFER_SIZE, FC_HEX))); + TRACEPRINTF(("val_from_float results in %s\n", fc_print(result, temp, CALC_BUFFER_SIZE, FC_PACKED))); return result; } @@ -1160,7 +1183,6 @@ LLDBL fc_val_to_float(const void *val) { const char *value; char *temp = NULL; - char *pack = NULL; int byte_offset; @@ -1172,42 +1194,47 @@ LLDBL fc_val_to_float(const void *val) value_t buildval; #ifdef HAVE_LONG_DOUBLE - char result_mantissa = 64; char result_exponent = 15; + char result_mantissa = 64; #else - char result_mantissa = 52; char result_exponent = 11; + char result_mantissa = 52; #endif temp = alloca(CALC_BUFFER_SIZE); - pack = alloca(VALUE_SIZE); +#ifdef HAVE_EXPLICIT_ONE + value = fc_cast(val, result_exponent, result_mantissa-1, temp); +#else value = fc_cast(val, result_exponent, result_mantissa, temp); +#endif sign = _sign(value); - /* long double exponent is 15bit, so the use of sc_val_to_long should not + + /* @@@ long double exponent is 15bit, so the use of sc_val_to_long should not * lead to wrong results */ exponent = sc_val_to_long(_exp(value)) ; - _pack(value, pack); + sc_val_from_ulong(2, NULL); + _shift_right(_mant(value), sc_get_buffer(), _mant(value)); mantissa0 = 0; mantissa1 = 0; for (byte_offset = 0; byte_offset < 4; byte_offset++) - mantissa1 |= sc_sub_bits(pack, result_mantissa, byte_offset) << (byte_offset<<3); + mantissa1 |= sc_sub_bits(_mant(value), result_mantissa, byte_offset) << (byte_offset<<3); for (; (byte_offset<<3) < result_mantissa; byte_offset++) - mantissa0 |= sc_sub_bits(pack, result_mantissa, byte_offset) << ((byte_offset-4)<<3); + mantissa0 |= sc_sub_bits(_mant(value), result_mantissa, byte_offset) << ((byte_offset-4)<<3); #ifndef HAVE_LONG_DOUBLE - mantissa0 &= 0x000FFFFF; + mantissa0 &= 0x000FFFFF; /* get rid of garbage */ #endif #ifdef HAVE_LONG_DOUBLE - buildval.val.high = sign << 31; - buildval.val.high |= exponent << 16; - buildval.val.mid = mantissa1; - buildval.val.low = mantissa0; + buildval.val.high = sign << 15; + buildval.val.high |= exponent; + buildval.val.mid = mantissa0; + buildval.val.low = mantissa1; #else /* no long double */ buildval.val.high = sign << 31; buildval.val.high |= exponent << 20; @@ -1216,7 +1243,6 @@ LLDBL fc_val_to_float(const void *val) #endif TRACEPRINTF(("val_to_float: %d-%x-%x%x\n", sign, exponent, mantissa0, mantissa1)); - //printf("val_to_float: %d-%x-%x%x\n", sign, exponent, mantissa0, mantissa1); return buildval.d; } @@ -1227,7 +1253,7 @@ char* fc_cast(const void *val, char exp_size, char mant_size, char *result) int exp_offset, val_bias, res_bias; if (result == NULL) result = calc_buffer; - temp = alloca(CALC_BUFFER_SIZE); + temp = alloca(VALUE_SIZE); if (_desc(value).exponent_size == exp_size && _desc(value).mantissa_size == mant_size) { @@ -1247,15 +1273,24 @@ char* fc_cast(const void *val, char exp_size, char mant_size, char *result) * offset and add it */ val_bias = (1<<_desc(value).exponent_size)/2-1; res_bias = (1<= 8+_sign(val)) sprintf(buf, "%sINFINITY", _sign(val)?"-":""); + else snprintf(buf, buflen, "%sINF", _sign(val)?"-":NULL); + break; + case NAN: + snprintf(buf, buflen, "NAN"); + break; + case ZERO: + snprintf(buf, buflen, "0.0"); + break; + default: +#ifdef HAVE_LONG_DOUBLE + snprintf(buf, buflen, "%LA", fc_val_to_float(val)); +#else + snprintf(buf, buflen, "%A", fc_val_to_float(val)); +#endif + } + break; + + case FC_PACKED: + default: + snprintf(buf, buflen, "%s", sc_print(_pack(val, mul_1), VALUE_SIZE*4, SC_HEX)); break; } return buf; @@ -1496,9 +1554,23 @@ void init_fltcalc(int precision) calc_buffer = malloc(CALC_BUFFER_SIZE); DEBUGPRINTF(("init fltcalc:\n\tVALUE_SIZE = %d\n\tSIGN_POS = %d\n\tEXPONENT_POS = %d\n\tMANTISSA_POS = %d\n\tDESCRIPTOR_POS = %d\n\tCALC_BUFFER_SIZE = %d\n\tcalc_buffer = %p\n\n", VALUE_SIZE, SIGN_POS, EXPONENT_POS, MANTISSA_POS, DESCRIPTOR_POS, CALC_BUFFER_SIZE, calc_buffer)); +#ifdef HAVE_LONG_DOUBLE + DEBUGPRINTF(("\tUsing long double (1-15-64) interface\n")); +#else + DEBUGPRINTF(("\tUsing double (1-11-52) interface\n")); +#endif +#ifdef WORDS_BIGENDIAN + DEBUGPRINTF(("\tWord order is big endian\n\n")); +#else + DEBUGPRINTF(("\tWord order is little endian\n\n")); +#endif } } +void finish_fltcalc (void) { + free(calc_buffer); calc_buffer = NULL; +} + /* definition of interface functions */ FC_DEFINE2(add) FC_DEFINE2(sub)