X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftv%2Fstrcalc.c;h=dd2e6a3f277adcf13d7496b7211b566c807c700c;hb=93a3661e3fb02276b3ccc27db7ede68f708bd306;hp=4799bd4cdcbc8ef254044419b852d63f22e498a4;hpb=3721d0d7ccdd7ead0be29de6010e4ff5cdb8f1fd;p=libfirm diff --git a/ir/tv/strcalc.c b/ir/tv/strcalc.c index 4799bd4cd..dd2e6a3f2 100644 --- a/ir/tv/strcalc.c +++ b/ir/tv/strcalc.c @@ -32,6 +32,7 @@ #include /* definition of LONG_MIN, used in sc_get_val_from_long */ #include "strcalc.h" +#include "xmalloc.h" /* * local definitions and macros @@ -76,6 +77,7 @@ static int carry_flag; /**< some computation set the carry_flag: However, the meaning of carry is machine dependent and often defined in other ways! */ +static const char sex_digit[4] = { SC_E, SC_C, SC_8, SC_0 }; static const char max_digit[4] = { SC_0, SC_1, SC_3, SC_7 }; static const char min_digit[4] = { SC_F, SC_E, SC_C, SC_8 }; @@ -415,7 +417,7 @@ static char const shrs_table[16][4][2] = { { {SC_F, SC_0}, {SC_7, SC_8}, {SC_3, SC_C}, {SC_1, SC_E} } }; -/* for converting to binary string */ +/** converting a digit to a binary string */ static const char *binary_table[16] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" @@ -821,7 +823,7 @@ static void _shl(const char *val1, char *buffer, long offset, int radius, unsign } else if (is_signed && !_bitisset(buffer[offset], bitoffset)) { - /* this unsets the upper bits of the leftmost digit */ + /* this clears the upper bits of the leftmost digit */ buffer[offset] = and_table[_val(buffer[offset])][_val(max_digit[bitoffset])]; for (counter = offset+1; counter < calc_buffer_size; counter++) { @@ -932,7 +934,7 @@ static void _rot(const char *val1, char *buffer, long offset, int radius, unsign offset = offset % radius; - /* rotation by multiples of the typelength is identity */ + /* rotation by multiples of the type length is identity */ if (offset == 0) { memmove(buffer, val1, calc_buffer_size); return; @@ -952,13 +954,34 @@ const void *sc_get_buffer(void) return (void*)calc_buffer; } -const int sc_get_buffer_length(void) +int sc_get_buffer_length(void) { return calc_buffer_size; } -/* XXX doesn't check for overflows */ -void sc_val_from_str(const char *str, unsigned int len, void *buffer) +/** + * Do sign extension if the mode is signed, expects all upper bits + * cleared. + */ +void sign_extend(char *calc_buffer, ir_mode *mode) { + if (mode_is_signed(mode)) { + int bits = get_mode_size_bits(mode) - 1; + int ofs = bits >> 2; + int max = max_digit[bits & 3]; + int i; + + if (calc_buffer[ofs] > max) { + /* sign bit is set, we need sign expansion */ + + for (i = ofs + 1; i < calc_buffer_size; ++i) + calc_buffer[i] = SC_F; + calc_buffer[ofs] = or_table[calc_buffer[ofs]][sex_digit[bits & 3]]; + } + } +} + +/* FIXME doesn't check for overflows */ +void sc_val_from_str(const char *str, unsigned int len, void *buffer, ir_mode *mode) { const char *orig_str = str; unsigned int orig_len = len; @@ -977,8 +1000,8 @@ void sc_val_from_str(const char *str, unsigned int len, void *buffer) if (buffer == NULL) buffer = calc_buffer; CLEAR_BUFFER(buffer); - memset(base, SC_0, calc_buffer_size); - memset(val, SC_0, calc_buffer_size); + CLEAR_BUFFER(base); + CLEAR_BUFFER(val); /* strip leading spaces */ while ((len > 0) && (*str == ' ')) { len--; str++; } @@ -1101,9 +1124,10 @@ void sc_val_from_str(const char *str, unsigned int len, void *buffer) } /* while (len > 0 ) */ if (sign) - { _negate(calc_buffer, calc_buffer); - } + + /* beware: even if hex numbers have no sign, we need sign extension here */ + sign_extend(calc_buffer, mode); } void sc_val_from_long(long value, void *buffer) @@ -1117,7 +1141,7 @@ void sc_val_from_long(long value, void *buffer) sign = (value < 0); is_minlong = value == LONG_MIN; - /* use absolute value, special treatment of MIN_LONG */ + /* use absolute value, special treatment of MIN_LONG to avoid overflow */ if (sign) { if (is_minlong) value = -(value+1); @@ -1133,7 +1157,6 @@ void sc_val_from_long(long value, void *buffer) value >>= 4; } - if (sign) { if (is_minlong) _inc(buffer, buffer); @@ -1144,14 +1167,14 @@ void sc_val_from_long(long value, void *buffer) void sc_val_from_ulong(unsigned long value, void *buffer) { - char *pos; + unsigned char *pos; if (buffer == NULL) buffer = calc_buffer; pos = buffer; - while (pos < (char*)buffer + calc_buffer_size) + while (pos < (unsigned char *)buffer + calc_buffer_size) { - *pos++ = _digit(value & 0xf); + *pos++ = (unsigned char)_digit(value & 0xf); value >>= 4; } } @@ -1403,8 +1426,8 @@ int sc_had_carry(void) unsigned char sc_sub_bits(const void *value, int len, unsigned byte_ofs) { - const char *val = (const char *)value; - unsigned nibble_ofs = 2 * byte_ofs; + const char *val = (const char *)value; + int nibble_ofs = 2 * byte_ofs; unsigned char res; /* the current scheme uses one byte to store a nibble */ @@ -1420,7 +1443,7 @@ unsigned char sc_sub_bits(const void *value, int len, unsigned byte_ofs) /* * convert to a string - * XXX Doesn't check buffer bounds + * FIXME: Doesn't check buffer bounds */ const char *sc_print(const void *value, unsigned bits, enum base_t base) { @@ -1520,13 +1543,13 @@ const char *sc_print(const void *value, unsigned bits, enum base_t base) if (base == SC_DEC) { /* check for negative values */ if (_bit(val, bits - 1)) { - _negate(val, div2_res); - sign = 1; - p = div2_res; + _negate(val, div2_res); + sign = 1; + p = div2_res; } } - /* transfer data into oscilating buffers */ + /* transfer data into oscillating buffers */ memset(div1_res, SC_0, calc_buffer_size); for (counter = 0; counter < nibbles; ++counter) div1_res[counter] = p[counter]; @@ -1578,13 +1601,8 @@ void init_strcalc(int precision) calc_buffer_size = (precision / 2); max_value_size = (precision / 4); - calc_buffer = malloc(calc_buffer_size+1 * sizeof(char)); - output_buffer = malloc(bit_pattern_size+1 * sizeof(char)); - - if (calc_buffer == NULL || output_buffer == NULL) { - assert(0 && "malloc failed"); - exit(-1); - } + calc_buffer = xmalloc(calc_buffer_size+1 * sizeof(char)); + output_buffer = xmalloc(bit_pattern_size+1 * sizeof(char)); DEBUGPRINTF(("init strcalc: \n\tPRECISION: %d\n\tCALC_BUFFER_SIZE = %d\n\tMAX_VALUE_SIZE = %d\n\tbuffer pointer: %p\n", precision, calc_buffer_size, max_value_size, calc_buffer)); }