X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftv%2Ffltcalc.c;h=973faf7452ff1b9fcf0e4a0442a08b59cae8e611;hb=b5bfe78cd888b9349d3dffd9e103da389a54ed09;hp=7d20bab5b5b2b2f71e45eee69df2c6dc90a8b726;hpb=354ec538057abddc8b757c5b0ba8e3c15115438b;p=libfirm diff --git a/ir/tv/fltcalc.c b/ir/tv/fltcalc.c index 7d20bab5b..973faf745 100644 --- a/ir/tv/fltcalc.c +++ b/ir/tv/fltcalc.c @@ -25,9 +25,7 @@ * @version $Id$ */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif +#include "config.h" #include "fltcalc.h" #include "strcalc.h" @@ -41,12 +39,8 @@ #ifdef HAVE_INTTYPES_H # include #endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STDLIB_H -# include -#endif +#include +#include #include #include @@ -182,6 +176,8 @@ static void *pack(const fp_value *int_float, void *packed) { default: break; } + assert(int_float->desc.explicit_one <= 1); + /* pack sign: move it to the left after exponent AND mantissa */ sc_val_from_ulong(int_float->sign, temp); @@ -397,16 +393,19 @@ static int normalize(const fp_value *in_val, fp_value *out_val, int sticky) { } /** - * Operations involving NaN's must return NaN + * Operations involving NaN's must return NaN. + * They are NOT exact. */ #define handle_NAN(a, b, result) \ do { \ if (a->desc.clss == NAN) { \ if (a != result) memcpy(result, a, calc_buffer_size); \ + fc_exact = 0; \ return; \ } \ if (b->desc.clss == NAN) { \ if (b != result) memcpy(result, b, calc_buffer_size); \ + fc_exact = 0; \ return; \ } \ }while (0) @@ -435,6 +434,7 @@ static void _fadd(const fp_value *a, const fp_value *b, fp_value *result) { /* produce NaN on inf - inf */ if (sign && (a->desc.clss == INF) && (b->desc.clss == INF)) { + fc_exact = 0; fc_get_qnan(&a->desc, result); return; } @@ -474,12 +474,14 @@ static void _fadd(const fp_value *a, const fp_value *b, fp_value *result) { if (a->desc.clss == ZERO || b->desc.clss == INF) { if (b != result) memcpy(result, b, calc_buffer_size); + fc_exact = b->desc.clss == NORMAL; result->sign = res_sign; return; } if (b->desc.clss == ZERO || a->desc.clss == INF) { if (a != result) memcpy(result, a, calc_buffer_size); + fc_exact = a->desc.clss == NORMAL; result->sign = res_sign; return; } @@ -548,9 +550,10 @@ static void _fmul(const fp_value *a, const fp_value *b, fp_value *result) { /* produce NaN on 0 * inf */ if (a->desc.clss == ZERO) { - if (b->desc.clss == INF) + if (b->desc.clss == INF) { fc_get_qnan(&a->desc, result); - else { + fc_exact = 0; + } else { if (a != result) memcpy(result, a, calc_buffer_size); result->sign = res_sign; @@ -558,9 +561,10 @@ static void _fmul(const fp_value *a, const fp_value *b, fp_value *result) { return; } if (b->desc.clss == ZERO) { - if (a->desc.clss == INF) + if (a->desc.clss == INF) { fc_get_qnan(&a->desc, result); - else { + fc_exact = 0; + } else { if (b != result) memcpy(result, b, calc_buffer_size); result->sign = res_sign; @@ -569,12 +573,14 @@ static void _fmul(const fp_value *a, const fp_value *b, fp_value *result) { } if (a->desc.clss == INF) { + fc_exact = 0; if (a != result) memcpy(result, a, calc_buffer_size); result->sign = res_sign; return; } if (b->desc.clss == INF) { + fc_exact = 0; if (b != result) memcpy(result, b, calc_buffer_size); result->sign = res_sign; @@ -631,10 +637,11 @@ static void _fdiv(const fp_value *a, const fp_value *b, fp_value *result) { /* produce NAN on 0/0 and inf/inf */ if (a->desc.clss == ZERO) { - if (b->desc.clss == ZERO) + if (b->desc.clss == ZERO) { /* 0/0 -> NaN */ fc_get_qnan(&a->desc, result); - else { + fc_exact = 0; + } else { /* 0/x -> a */ if (a != result) memcpy(result, a, calc_buffer_size); @@ -644,10 +651,11 @@ static void _fdiv(const fp_value *a, const fp_value *b, fp_value *result) { } if (b->desc.clss == INF) { - if (a->desc.clss == INF) + fc_exact = 0; + if (a->desc.clss == INF) { /* inf/inf -> NaN */ fc_get_qnan(&a->desc, result); - else { + } else { /* x/inf -> 0 */ sc_val_from_ulong(0, NULL); _save_result(_exp(result)); @@ -658,6 +666,7 @@ static void _fdiv(const fp_value *a, const fp_value *b, fp_value *result) { } if (a->desc.clss == INF) { + fc_exact = 0; /* inf/x -> inf */ if (a != result) memcpy(result, a, calc_buffer_size); @@ -665,6 +674,7 @@ static void _fdiv(const fp_value *a, const fp_value *b, fp_value *result) { return; } if (b->desc.clss == ZERO) { + fc_exact = 0; /* division by zero */ if (result->sign) fc_get_minusinf(&a->desc, result); @@ -801,7 +811,10 @@ static void _trunc(const fp_value *a, fp_value *result) { /* and the mask and return the result */ sc_and(_mant(a), temp, _mant(result)); - if (a != result) memcpy(_exp(result), _exp(a), value_size); + if (a != result) { + memcpy(_exp(result), _exp(a), value_size); + result->sign = a->sign; + } } /******** @@ -1002,7 +1015,7 @@ done: ieee_descriptor_t tmp_desc; (void) len; -#ifdef HAVE_LONG_DOUBLE +#if defined(HAVE_LONG_DOUBLE) && !defined(__CYGWIN__) val = strtold(str, NULL); DEBUGPRINTF(("val_from_str(%s)\n", str)); tmp_desc.exponent_size = 15; @@ -1024,10 +1037,11 @@ done: } fp_value *fc_val_from_ieee754(LLDBL l, const ieee_descriptor_t *desc, fp_value *result) { - char *temp; - int bias_res, bias_val, mant_val; + char *temp; + int bias_res, bias_val, mant_val; value_t srcval; - UINT32 sign, exponent, mantissa0, mantissa1; + char sign; + UINT32 exponent, mantissa0, mantissa1; srcval.d = l; bias_res = ((1 << (desc->exponent_size - 1)) - 1); @@ -1140,6 +1154,7 @@ LLDBL fc_val_to_ieee754(const fp_value *val) { value_t buildval; ieee_descriptor_t desc; + unsigned mantissa_size; #ifdef HAVE_LONG_DOUBLE desc.exponent_size = 15; @@ -1152,6 +1167,7 @@ LLDBL fc_val_to_ieee754(const fp_value *val) { desc.explicit_one = 0; desc.clss = NORMAL; #endif + mantissa_size = desc.mantissa_size + desc.explicit_one; temp = alloca(calc_buffer_size); value = fc_cast(val, &desc, temp); @@ -1169,10 +1185,10 @@ LLDBL fc_val_to_ieee754(const fp_value *val) { mantissa1 = 0; for (byte_offset = 0; byte_offset < 4; byte_offset++) - mantissa1 |= sc_sub_bits(_mant(value), desc.mantissa_size, byte_offset) << (byte_offset<<3); + mantissa1 |= sc_sub_bits(_mant(value), mantissa_size, byte_offset) << (byte_offset << 3); for (; (byte_offset<<3) < desc.mantissa_size; byte_offset++) - mantissa0 |= sc_sub_bits(_mant(value), desc.mantissa_size, byte_offset) << ((byte_offset-4)<<3); + mantissa0 |= sc_sub_bits(_mant(value), mantissa_size, byte_offset) << ((byte_offset - 4) << 3); #ifdef HAVE_LONG_DOUBLE buildval.val.high = sign << 15; @@ -1319,7 +1335,7 @@ fp_value *fc_get_plusinf(const ieee_descriptor_t *desc, fp_value *result) { result->desc.exponent_size = desc->exponent_size; result->desc.mantissa_size = desc->mantissa_size; result->desc.explicit_one = desc->explicit_one; - result->desc.clss = NORMAL; + result->desc.clss = INF; result->sign = 0; @@ -1408,6 +1424,7 @@ int fc_is_subnormal(const fp_value *a) { char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base) { char *mul_1; + LLDBL flt_val; mul_1 = alloca(calc_buffer_size); @@ -1415,22 +1432,21 @@ char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base) { case FC_DEC: switch ((value_class_t)val->desc.clss) { case INF: - if (buflen >= 8 + val->sign) sprintf(buf, "%sINFINITY", val->sign ? "-":""); - else snprintf(buf, buflen, "%sINF", val->sign ? "-":NULL); + snprintf(buf, buflen, "%cINF", val->sign ? '-' : '+'); break; case NAN: - snprintf(buf, buflen, "NAN"); + snprintf(buf, buflen, "NaN"); break; case ZERO: snprintf(buf, buflen, "0.0"); break; default: - /* XXX to be implemented */ + flt_val = fc_val_to_ieee754(val); #ifdef HAVE_LONG_DOUBLE /* XXX 30 is arbitrary */ - snprintf(buf, buflen, "%.30LE", fc_val_to_ieee754(val)); + snprintf(buf, buflen, "%.30LE", flt_val); #else - snprintf(buf, buflen, "%.18E", fc_val_to_ieee754(val)); + snprintf(buf, buflen, "%.18E", flt_val); #endif } break; @@ -1438,8 +1454,7 @@ char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base) { case FC_HEX: switch ((value_class_t)val->desc.clss) { case INF: - if (buflen >= 8+val->sign) sprintf(buf, "%sINFINITY", val->sign?"-":""); - else snprintf(buf, buflen, "%sINF", val->sign?"-":NULL); + snprintf(buf, buflen, "%cINF", val->sign ? '-' : '+'); break; case NAN: snprintf(buf, buflen, "NAN"); @@ -1448,10 +1463,11 @@ char *fc_print(const fp_value *val, char *buf, int buflen, unsigned base) { snprintf(buf, buflen, "0.0"); break; default: + flt_val = fc_val_to_ieee754(val); #ifdef HAVE_LONG_DOUBLE - snprintf(buf, buflen, "%LA", fc_val_to_ieee754(val)); + snprintf(buf, buflen, "%LA", flt_val); #else - snprintf(buf, buflen, "%A", fc_val_to_ieee754(val)); + snprintf(buf, buflen, "%A", flt_val); #endif } break; @@ -1469,7 +1485,7 @@ unsigned char fc_sub_bits(const fp_value *value, unsigned num_bits, unsigned byt /* this is used to cache the packed version of the value */ static char *packed_value = NULL; - if (packed_value == NULL) packed_value = xmalloc(value_size); + if (packed_value == NULL) packed_value = XMALLOCN(char, value_size); if (value != NULL) pack(value, packed_value); @@ -1674,6 +1690,7 @@ int fc_flt2int(const fp_value *a, void *result, ir_mode *dst_mode) { int exp_bias = (1 << (a->desc.exponent_size - 1)) - 1; int exp_val = sc_val_to_long(_exp(a)) - exp_bias; int shift, highest; + int mantissa_size; if (a->sign && !mode_is_signed(dst_mode)) { /* FIXME: for now we cannot convert this */ @@ -1681,12 +1698,14 @@ int fc_flt2int(const fp_value *a, void *result, ir_mode *dst_mode) { } assert(exp_val >= 0 && "floating point value not integral before fc_flt2int() call"); - shift = exp_val - (a->desc.mantissa_size + ROUNDING_BITS); + mantissa_size = a->desc.mantissa_size + ROUNDING_BITS; + shift = exp_val - mantissa_size; + mantissa_size += a->desc.explicit_one; if (shift > 0) { - sc_shlI(_mant(a), shift, 64, 0, result); + sc_shlI(_mant(a), shift, mantissa_size, 0, result); } else { - sc_shrI(_mant(a), -shift, 64, 0, result); + sc_shrI(_mant(a), -shift, mantissa_size, 0, result); } /* check for overflow */