X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftv%2Ftv.c;h=90d24bb7ad3bd40faa932986cb3544f0d5de6553;hb=464132f4d8840f7bb4228bfeef5484331bf50835;hp=5c6b09bfe19e5a004233907eb63ae5b68c0c26fb;hpb=ecdae24c2bf7aa79d8065255940faae70307d535;p=libfirm diff --git a/ir/tv/tv.c b/ir/tv/tv.c index 5c6b09bfe..90d24bb7a 100644 --- a/ir/tv/tv.c +++ b/ir/tv/tv.c @@ -191,13 +191,8 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode) case TV_OVERFLOW_WRAP: { char *temp = alloca(sc_get_buffer_length()); - char *diff = alloca(sc_get_buffer_length()); - sc_sub(get_mode_max(mode)->value, get_mode_min(mode)->value, diff); - sc_val_from_ulong(1, temp); - sc_add(diff, temp, diff); - sc_sub(value, diff, temp); - while (sc_comp(temp, get_mode_max(mode)->value) == 1) - sc_sub(temp, diff, temp); + sc_val_from_ulong(-1, temp); + sc_and(temp, value, temp); return get_tarval(temp, length, mode); } case TV_OVERFLOW_BAD: @@ -213,13 +208,8 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode) case TV_OVERFLOW_WRAP: { char *temp = alloca(sc_get_buffer_length()); - char *diff = alloca(sc_get_buffer_length()); - sc_sub(get_mode_max(mode)->value, get_mode_min(mode)->value, diff); - sc_val_from_ulong(1, temp); - sc_add(diff, temp, diff); - sc_add(value, diff, temp); - while (sc_comp(temp, get_mode_max(mode)->value) == 1) - sc_add(temp, diff, temp); + sc_val_from_ulong(-1, temp); + sc_and(temp, value, temp); return get_tarval(temp, length, mode); } case TV_OVERFLOW_BAD: @@ -1521,20 +1511,20 @@ int tarval_snprintf(char *buf, size_t len, tarval *tv) case irms_reference: if (tv == tv->mode->null) return snprintf(buf, len, "NULL"); - if (tv->value != NULL){ - if (len > tv->length) { - memcpy(buf, tv->value, tv->length); - buf[tv->length] = '\0'; - } - else { - /* truncated */ - memcpy(buf, tv->value, len-1); - buf[len-1] = '\0'; + if (tv->value != NULL) { + if (len > tv->length) { + memcpy(buf, tv->value, tv->length); + buf[tv->length] = '\0'; + } + else { + /* truncated */ + memcpy(buf, tv->value, len-1); + buf[len-1] = '\0'; + } + return tv->length; } - return tv->length; - } else - return snprintf(buf, len, "void"); + return snprintf(buf, len, "void"); case irms_internal_boolean: switch (mode_info->mode_output) { @@ -1664,7 +1654,33 @@ tarval_classification_t classify_tarval(tarval *tv) return TV_CLASSIFY_OTHER; } -/** +/* + * Returns non-zero if a given (integer) tarval has only one single bit + * set. + */ +int is_single_bit_tarval(tarval *tv) { + int i, l; + int bits; + + if (!tv || tv == tarval_bad) return 0; + if (! mode_is_int(tv->mode)) return 0; + + l = get_mode_size_bytes(tv->mode); + for (bits = 0, i = l - 1; i >= 0; --i) { + unsigned char v = get_tarval_sub_bits(tv, (unsigned)i); + + /* check for more than one bit in these */ + if (v) { + if (v & (v-1)) + return 0; + if (++bits > 1) + return 0; + } + } + return bits; +} + +/* * Sets the overflow mode for integer operations. */ void tarval_set_integer_overflow_mode(tarval_int_overflow_mode_t ov_mode) {