fix fehler89 by correctly truncating tarvals (wrote a new sc_truncate function)
authorMatthias Braun <matze@braunis.de>
Tue, 2 Oct 2007 07:46:21 +0000 (07:46 +0000)
committerMatthias Braun <matze@braunis.de>
Tue, 2 Oct 2007 07:46:21 +0000 (07:46 +0000)
[r16028]

ir/tv/strcalc.c
ir/tv/strcalc.h
ir/tv/tv.c

index dc68796..43d126b 100644 (file)
@@ -1180,6 +1180,23 @@ void sc_max_from_bits(unsigned int num_bits, unsigned int sign, void *buffer) {
                *pos++ = SC_0;
 }
 
+void sc_truncate(unsigned int num_bits, void *buffer) {
+       char *pos = buffer + (num_bits / 4);
+       char *end = buffer + calc_buffer_size;
+
+       assert(pos < end);
+
+       switch(num_bits % 4) {
+       case 0: /* nothing to do */ break;
+       case 1: *pos = and_table[_val(*pos)][SC_1]; pos++; break;
+       case 2: *pos = and_table[_val(*pos)][SC_3]; pos++; break;
+       case 3: *pos = and_table[_val(*pos)][SC_7]; pos++; break;
+       }
+
+       for( ; pos < end; ++pos)
+               *pos = SC_0;
+}
+
 int sc_comp(const void* value1, const void* value2) {
        int counter = calc_buffer_size - 1;
        const char *val1 = (const char *)value1;
@@ -1288,7 +1305,7 @@ unsigned char sc_sub_bits(const void *value, int len, unsigned byte_ofs) {
                res |= _val(val[nibble_ofs + 1]) << 4;
 
        /* kick bits outsize */
-       if (len < 8*byte_ofs) {
+       if (len < (int) (8*byte_ofs)) {
                res &= 0xFF >> (8*byte_ofs - len);
        }
        return res;
index ec666bc..49b3a28 100644 (file)
@@ -200,6 +200,9 @@ long sc_val_to_long(const void *val);
 void sc_min_from_bits(unsigned int num_bits, unsigned int sign, void *buffer);
 void sc_max_from_bits(unsigned int num_bits, unsigned int sign, void *buffer);
 
+/** truncates a value to lowest @p num_bits bits */
+void sc_truncate(unsigned num_bits, void *buffer);
+
 /**
  * Compares val1 and val2
  */
index eaa8886..0963813 100644 (file)
@@ -193,8 +193,8 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode)
        case irms_reference:
                /* addresses always wrap around */
                temp = alloca(sc_get_buffer_length());
-               sc_val_from_ulong(-1, temp);
-               sc_and(temp, value, temp);
+               memcpy(temp, sc_get_buffer(), sc_get_buffer_length());
+               sc_truncate(get_mode_size_bits(mode), temp);
                /* the sc_ module expects that all bits are set ... */
                sign_extend(temp, mode);
                return get_tarval(temp, length, mode);
@@ -206,8 +206,8 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode)
                                return get_mode_max(mode);
                        case TV_OVERFLOW_WRAP:
                                temp = alloca(sc_get_buffer_length());
-                               sc_val_from_ulong(-1, temp);
-                               sc_and(temp, value, temp);
+                               memcpy(temp, sc_get_buffer(), sc_get_buffer_length());
+                               sc_truncate(get_mode_size_bits(mode), temp);
                                /* the sc_ module expects that all bits are set ... */
                                sign_extend(temp, mode);
                                return get_tarval(temp, length, mode);
@@ -223,8 +223,8 @@ static tarval *get_tarval_overflow(const void *value, int length, ir_mode *mode)
                                return get_mode_min(mode);
                        case TV_OVERFLOW_WRAP: {
                                char *temp = alloca(sc_get_buffer_length());
-                               sc_val_from_ulong(-1, temp);
-                               sc_and(temp, value, temp);
+                               memcpy(temp, sc_get_buffer(), sc_get_buffer_length());
+                               sc_truncate(get_mode_size_bits(mode), temp);
                                return get_tarval(temp, length, mode);
                        }
                        case TV_OVERFLOW_BAD: