+fp_value *fc_add(const fp_value *a, const fp_value *b, fp_value *result)
+{
+ if (result == NULL) result = calc_buffer;
+
+ TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
+ TRACEPRINTF(("+ %s ", fc_print(b, buffer, sizeof(buffer), FC_PACKED)));
+
+ /* make the value with the bigger exponent the first one */
+ if (sc_comp(_exp(a), _exp(b)) == -1)
+ _fadd(b, a, result);
+ else
+ _fadd(a, b, result);
+
+ TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
+ return result;
+}
+
+fp_value *fc_sub(const fp_value *a, const fp_value *b, fp_value *result)
+{
+ fp_value *temp;
+
+ if (result == NULL) result = calc_buffer;
+
+ TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
+ TRACEPRINTF(("- %s ", fc_print(b, buffer, sizeof(buffer), FC_PACKED)));
+
+ temp = alloca(calc_buffer_size);
+ memcpy(temp, b, calc_buffer_size);
+ temp->sign = !b->sign;
+ if (sc_comp(_exp(a), _exp(temp)) == -1)
+ _fadd(temp, a, result);
+ else
+ _fadd(a, temp, result);
+
+ TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
+ return result;
+}
+
+fp_value *fc_mul(const fp_value *a, const fp_value *b, fp_value *result)
+{
+ if (result == NULL) result = calc_buffer;
+
+ TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
+ TRACEPRINTF(("* %s ", fc_print(b, buffer, sizeof(buffer), FC_PACKED)));
+
+ _fmul(a, b, result);
+
+ TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
+ return result;
+}
+
+fp_value *fc_div(const fp_value *a, const fp_value *b, fp_value *result)
+{
+ if (result == NULL) result = calc_buffer;
+
+ TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
+ TRACEPRINTF(("/ %s ", fc_print(b, buffer, sizeof(buffer), FC_PACKED)));
+
+ _fdiv(a, b, result);
+
+ TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
+ return result;
+}
+
+fp_value *fc_neg(const fp_value *a, fp_value *result)
+{
+ if (result == NULL) result = calc_buffer;
+
+ TRACEPRINTF(("- %s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
+
+ if (a != result)
+ memcpy(result, a, calc_buffer_size);
+ result->sign = !a->sign;
+
+ TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
+ return result;
+}
+
+fp_value *fc_int(const fp_value *a, fp_value *result)
+{
+ if (result == NULL) result = calc_buffer;
+
+ TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
+ TRACEPRINTF(("truncated to integer "));
+
+ _trunc(a, result);
+
+ TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
+ return result;
+}
+
+fp_value *fc_rnd(const fp_value *a, fp_value *result)
+{
+ if (result == NULL) result = calc_buffer;
+
+ (void) a;
+ TRACEPRINTF(("%s ", fc_print(a, buffer, sizeof(buffer), FC_PACKED)));
+ TRACEPRINTF(("rounded to integer "));
+
+ assert(!"fc_rnd() not yet implemented");
+
+ TRACEPRINTF(("= %s\n", fc_print(result, buffer, sizeof(buffer), FC_PACKED)));
+ return result;
+}
+
+/*
+ * convert a floating point value into an sc value ...
+ */
+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;
+
+ if (tgt_bits < mantissa_size + 1)
+ tgt_bits = mantissa_size + 1;
+ if (shift > 0) {
+ sc_shlI(_mant(a), shift, tgt_bits, 0, result);
+ } else {
+ sc_shrI(_mant(a), -shift, tgt_bits, 0, result);
+ }
+
+ /* check for overflow */
+ highest = sc_get_highest_set_bit(result);
+
+ if (mode_is_signed(dst_mode)) {
+ if (highest == sc_get_lowest_set_bit(result)) {
+ /* need extra test for MIN_INT */
+ if (highest >= (int) get_mode_size_bits(dst_mode)) {
+ /* FIXME: handle overflow */
+ return 0;
+ }
+ } else {
+ if (highest >= (int) get_mode_size_bits(dst_mode) - 1) {
+ /* FIXME: handle overflow */
+ return 0;
+ }
+ }
+ } else {
+ if (highest >= (int) get_mode_size_bits(dst_mode)) {
+ /* FIXME: handle overflow */
+ return 0;
+ }
+ }
+
+ if (a->sign)
+ sc_neg(result, result);
+
+ return 1;
+ }
+ else if (a->desc.clss == ZERO) {
+ sc_zero(result);
+ return 1;
+ }
+ return 0;
+}
+
+
+unsigned fc_set_immediate_precision(unsigned bits)
+{
+ unsigned old = immediate_prec;
+
+ immediate_prec = bits;
+ return old;
+}
+
+int fc_is_exact(void)
+{
+ return fc_exact;
+}