Commit b93f313a authored by Michael Beck's avatar Michael Beck
Browse files

Add support for float->int conversion (no overflow handling yet)

[r15709]
parent 81f1a041
......@@ -1636,6 +1636,61 @@ fp_value *fc_rnd(const fp_value *a, fp_value *result) {
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;
if (a->sign && !mode_is_signed(dst_mode)) {
/* FIXME: for now we cannot convert this */
return 0;
}
assert(exp_val >= 0 && "floating point value not integral before fc_flt2int() call");
shift = a->desc.mantissa_size - exp_val + 2;
sc_shrI(_mant(a), shift, 64, 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 >= get_mode_size_bits(dst_mode)) {
/* FIXME: handle overflow */
return 0;
}
} else {
if (highest >= get_mode_size_bits(dst_mode) - 1) {
/* FIXME: handle overflow */
return 0;
}
}
} else {
if (highest >= 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;
......
......@@ -28,6 +28,7 @@
#define FIRM_TV_FLTCALC_H
#include "firm_config.h"
#include "firm_types.h"
#ifdef HAVE_LONG_DOUBLE
/* XXX Set this via autoconf */
......@@ -170,6 +171,11 @@ char *fc_print(const fp_value *a, char *buf, int buflen, unsigned base);
*/
int fc_comp(const fp_value *a, const fp_value *b);
/**
* Converts an floating point value into an integer value.
*/
int fc_flt2int(const fp_value *a, void *result, ir_mode *dst_mode);
/**
* Returns non-zero if the mantissa is zero, i.e. 1.0Exxx
*/
......
......@@ -1503,7 +1503,6 @@ void sc_sub(const void *value1, const void *value2, void *buffer) {
}
void sc_neg(const void *value1, void *buffer) {
CLEAR_BUFFER(calc_buffer);
carry_flag = 0;
DEBUGPRINTF_COMPUTATION(("- %s ->", sc_print_hex(value1)));
......@@ -1662,9 +1661,7 @@ void sc_shl(const void *val1, const void *val2, int radius, int sign, void *buff
}
}
void sc_shr(const void *val1, const void *val2, int radius, int sign, void *buffer) {
long offset = sc_val_to_long(val2);
void sc_shrI(const void *val1, long offset, int radius, int sign, void *buffer) {
carry_flag = 0;
DEBUGPRINTF_COMPUTATION(("%s >>u %ld ", sc_print_hex(value1), offset));
......@@ -1677,6 +1674,12 @@ void sc_shr(const void *val1, const void *val2, int radius, int sign, void *buff
}
}
void sc_shr(const void *val1, const void *val2, int radius, int sign, void *buffer) {
long offset = sc_val_to_long(val2);
sc_shrI(val1, offset, radius, sign, buffer);
}
void sc_shrs(const void *val1, const void *val2, int radius, int sign, void *buffer) {
long offset = sc_val_to_long(val2);
......@@ -1706,3 +1709,10 @@ void sc_rot(const void *val1, const void *val2, int radius, int sign, void *buff
memmove(buffer, calc_buffer, calc_buffer_size);
}
}
void sc_zero(void *buffer) {
if (buffer == NULL)
buffer = calc_buffer;
CLEAR_BUFFER(buffer);
carry_flag = 0;
}
......@@ -148,6 +148,11 @@ void sc_divmod(const void *value1, const void *value2, void *div_buffer, void *m
*/
void sc_shl(const void *value1, const void *value2, int radius, int sign, void *buffer);
/**
* buffer = value1 >>u offset
*/
void sc_shrI(const void *val1, long offset, int radius, int sign, void *buffer);
/**
* buffer = value1 >>u value2
*/
......@@ -163,6 +168,11 @@ void sc_shrs(const void *value1, const void *value2, int radius, int sign, void
*/
void sc_rot(const void *value1, const void *value2, int radius, int sign, void *buffer);
/**
* buffer = 0
*/
void sc_zero(void *buffer);
/*
* function declarations
*/
......
......@@ -782,13 +782,14 @@ pn_Cmp tarval_cmp(tarval *a, tarval *b) {
/*
* convert to other mode
*/
tarval *tarval_convert_to(tarval *src, ir_mode *m) {
tarval *tarval_convert_to(tarval *src, ir_mode *dst_mode) {
char *buffer;
fp_value *res;
assert(src);
assert(m);
assert(dst_mode);
if (src->mode == m) return src;
if (src->mode == dst_mode) return src;
if (get_mode_n_vector_elems(src->mode) > 1) {
/* vector arithmetic not implemented yet */
......@@ -803,9 +804,9 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) {
/* cast float to something */
case irms_float_number:
switch (get_mode_sort(m)) {
switch (get_mode_sort(dst_mode)) {
case irms_float_number:
switch (get_mode_size_bits(m)) {
switch (get_mode_size_bits(dst_mode)) {
case 32:
fc_cast(src->value, 8, 23, NULL);
break;
......@@ -818,25 +819,23 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) {
default:
break;
}
return get_tarval(fc_get_buffer(), fc_get_buffer_length(), m);
return get_tarval(fc_get_buffer(), fc_get_buffer_length(), dst_mode);
case irms_int_number:
switch (GET_FLOAT_TO_INT_MODE()) {
case TRUNCATE:
fc_int(src->value, NULL);
res = fc_int(src->value, NULL);
break;
case ROUND:
fc_rnd(src->value, NULL);
res = fc_rnd(src->value, NULL);
break;
default:
assert(0);
break;
}
/* FIXME: floating point unit can't produce a value in integer
* representation
* an intermediate representation is needed here first. */
/* return get_tarval(); */
return tarval_bad;
if (! fc_flt2int(res, sc_get_buffer(), dst_mode))
return tarval_bad;
return get_tarval(sc_get_buffer(), sc_get_buffer_length(), dst_mode);
default:
/* the rest can't be converted */
......@@ -846,14 +845,14 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) {
/* cast int/characters to something */
case irms_int_number:
switch (get_mode_sort(m)) {
switch (get_mode_sort(dst_mode)) {
case irms_reference:
case irms_int_number:
buffer = alloca(sc_get_buffer_length());
memcpy(buffer, src->value, sc_get_buffer_length());
sign_extend(buffer, m);
return get_tarval_overflow(buffer, src->length, m);
sign_extend(buffer, dst_mode);
return get_tarval_overflow(buffer, src->length, dst_mode);
case irms_internal_boolean:
/* XXX C semantics */
......@@ -870,7 +869,7 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) {
snprintf(buffer, 100, "%s",
sc_print(src->value, get_mode_size_bits(src->mode), SC_DEC, mode_is_signed(src->mode)));
buffer[100 - 1] = '\0';
switch (get_mode_size_bits(m)) {
switch (get_mode_size_bits(dst_mode)) {
case 32:
fc_val_from_str(buffer, 0, 8, 23, NULL);
break;
......@@ -881,7 +880,7 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) {
fc_val_from_str(buffer, 0, 15, 64, NULL);
break;
}
return get_tarval(fc_get_buffer(), fc_get_buffer_length(), m);
return get_tarval(fc_get_buffer(), fc_get_buffer_length(), dst_mode);
default:
break;
......@@ -890,16 +889,16 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) {
case irms_internal_boolean:
/* beware: this is C semantic for the INTERNAL boolean mode */
if (get_mode_sort(m) == irms_int_number)
return src == tarval_b_true ? get_mode_one(m) : get_mode_null(m);
if (get_mode_sort(dst_mode) == irms_int_number)
return src == tarval_b_true ? get_mode_one(dst_mode) : get_mode_null(dst_mode);
break;
case irms_reference:
if (get_mode_sort(m) == irms_int_number) {
if (get_mode_sort(dst_mode) == irms_int_number) {
buffer = alloca(sc_get_buffer_length());
memcpy(buffer, src->value, sc_get_buffer_length());
sign_extend(buffer, src->mode);
return get_tarval_overflow(buffer, src->length, m);
return get_tarval_overflow(buffer, src->length, dst_mode);
}
break;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment