Support dtor sections on Mach-O.
[libfirm] / ir / tv / fltcalc.c
index 973faf7..d6105a8 100644 (file)
  * @author   Mathias Heil
  * @version  $Id$
  */
-
 #include "config.h"
 
 #include "fltcalc.h"
 #include "strcalc.h"
 
-#include <math.h>    /* need isnan() and isinf() (will be changed)*/
+#include <math.h>
 /* undef some reused constants defined by math.h */
 #ifdef NAN
 #  undef NAN
 #endif
 
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
+#include <inttypes.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -1228,6 +1225,12 @@ fp_value *fc_cast(const fp_value *value, const ieee_descriptor_t *desc, fp_value
                else
                        return fc_get_snan(desc, result);
        }
+       else if(value->desc.clss == INF) {
+               if (value->sign == 0)
+                       return fc_get_plusinf(desc, result);
+               else
+                       return fc_get_minusinf(desc, result);
+       }
 
        /* set the descriptor of the new value */
        result->desc.exponent_size = desc->exponent_size;
@@ -1329,7 +1332,10 @@ fp_value *fc_get_qnan(const ieee_descriptor_t *desc, fp_value *result) {
        return result;
 }
 
-fp_value *fc_get_plusinf(const ieee_descriptor_t *desc, fp_value *result) {
+fp_value *fc_get_plusinf(const ieee_descriptor_t *desc, fp_value *result)
+{
+       char *mant;
+
        if (result == NULL) result = calc_buffer;
 
        result->desc.exponent_size = desc->exponent_size;
@@ -1341,7 +1347,11 @@ fp_value *fc_get_plusinf(const ieee_descriptor_t *desc, fp_value *result) {
 
        sc_val_from_ulong((1 << desc->exponent_size) - 1, _exp(result));
 
-       sc_val_from_ulong(0, _mant(result));
+       mant = _mant(result);
+       sc_val_from_ulong(0, mant);
+       if (desc->explicit_one) {
+               sc_set_bit_at(mant, result->desc.mantissa_size + ROUNDING_BITS);
+       }
 
        return result;
 }
@@ -1525,7 +1535,7 @@ int fc_can_lossless_conv_to(const fp_value *value, const ieee_descriptor_t *desc
        if (0 < v && v < (1 << desc->exponent_size) - 1) {
                /* exponent can be encoded, now check the mantissa */
                v = value->desc.mantissa_size + ROUNDING_BITS - sc_get_lowest_set_bit(_mant(value));
-               return v < desc->mantissa_size;
+               return v <= desc->mantissa_size;
        }
        return 0;
 }
@@ -1685,27 +1695,34 @@ fp_value *fc_rnd(const fp_value *a, fp_value *result) {
 /*
  * convert a floating point value into an sc value ...
  */
-int fc_flt2int(const fp_value *a, void *result, ir_mode *dst_mode) {
+int fc_flt2int(const fp_value *a, void *result, ir_mode *dst_mode)
+{
        if (a->desc.clss == NORMAL) {
                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;
+               int tgt_bits;
 
                if (a->sign && !mode_is_signed(dst_mode)) {
                        /* FIXME: for now we cannot convert this */
                        return 0;
                }
 
+               tgt_bits = get_mode_size_bits(dst_mode);
+               if (mode_is_signed(dst_mode))
+                       --tgt_bits;
+
                assert(exp_val >= 0 && "floating point value not integral before fc_flt2int() call");
                mantissa_size = a->desc.mantissa_size + ROUNDING_BITS;
                shift         = exp_val - mantissa_size;
 
-               mantissa_size += a->desc.explicit_one;
+               if (tgt_bits < mantissa_size + 1)
+                       tgt_bits = mantissa_size + 1;
                if (shift > 0) {
-                       sc_shlI(_mant(a),  shift, mantissa_size, 0, result);
+                       sc_shlI(_mant(a),  shift, tgt_bits, 0, result);
                } else {
-                       sc_shrI(_mant(a), -shift, mantissa_size, 0, result);
+                       sc_shrI(_mant(a), -shift, tgt_bits, 0, result);
                }
 
                /* check for overflow */