X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftv%2Fstrcalc.c;h=50aaf56896fe0a58115b19d22fc6cb4843b15d41;hb=0d61f4e9a295d71deca66e1580273e484e7f0f9f;hp=e7cbc8c0a40768612f09fffb7ca975205a627d69;hpb=786de5e2a2b023c77b600569b8a82308d0fb9ada;p=libfirm diff --git a/ir/tv/strcalc.c b/ir/tv/strcalc.c index e7cbc8c0a..50aaf5689 100644 --- a/ir/tv/strcalc.c +++ b/ir/tv/strcalc.c @@ -40,11 +40,10 @@ * local definitions and macros */ #define CLEAR_BUFFER(b) assert(b); memset(b, SC_0, calc_buffer_size) +#define SHIFT(count) (SC_1 << (count)) #define _val(a) ((a)-SC_0) #define _digit(a) ((a)+SC_0) -#define _bitisset(digit, pos) ((digit & shift_table[pos]) != SC_0) - -#define fail_char(a, b, c, d) _fail_char((a), (b), (c), (d), __FILE__, __LINE__) +#define _bitisset(digit, pos) (((digit) & SHIFT(pos)) != SC_0) /* shortcut output for debugging */ # define sc_print_hex(a) sc_print((a), 0, SC_HEX, 0) @@ -84,8 +83,6 @@ static const char zex_digit[4] = { SC_1, SC_3, SC_7, SC_F }; 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 }; -static const char shift_table[4] = { SC_1, SC_2, SC_4, SC_8 }; - static char const add_table[16][16][2] = { { {SC_0, SC_0}, {SC_1, SC_0}, {SC_2, SC_0}, {SC_3, SC_0}, {SC_4, SC_0}, {SC_5, SC_0}, {SC_6, SC_0}, {SC_7, SC_0}, @@ -278,19 +275,12 @@ static const char *binary_table[16] = { /***************************************************************************** * private functions *****************************************************************************/ -static void _fail_char(const char *str, size_t len, const char fchar, int pos, - const char *file, int line) { - printf("ERROR:\n"); - printf("Unexpected character '%c' in %s:%d\n", fchar, file, line); - while (len-- && *str) printf("%c", *str++); printf("\n"); - while (--pos) printf(" "); printf("^\n"); - exit(-1); -} /** * implements the bitwise NOT operation */ -static void do_bitnot(const char *val, char *buffer) { +static void do_bitnot(const char *val, char *buffer) +{ int counter; for (counter = 0; counter> 2; @@ -350,7 +356,8 @@ static int do_bit(const char *val, int pos) { /** * Implements a fast ADD + 1 */ -static void do_inc(const char *val, char *buffer) { +static void do_inc(const char *val, char *buffer) +{ int counter = 0; while (counter++ < calc_buffer_size) { @@ -370,7 +377,8 @@ static void do_inc(const char *val, char *buffer) { /** * Implements a unary MINUS */ -static void do_negate(const char *val, char *buffer) { +static void do_negate(const char *val, char *buffer) +{ do_bitnot(val, buffer); do_inc(buffer, buffer); } @@ -381,7 +389,8 @@ static void do_negate(const char *val, char *buffer) { * @todo The implementation of carry is wrong, as it is the * calc_buffer_size carry, not the mode depending */ -static void do_add(const char *val1, const char *val2, char *buffer) { +static void do_add(const char *val1, const char *val2, char *buffer) +{ int counter; const char *add1, *add2; char carry = SC_0; @@ -399,7 +408,8 @@ static void do_add(const char *val1, const char *val2, char *buffer) { /** * Implements a binary SUB */ -static void do_sub(const char *val1, const char *val2, char *buffer) { +static void do_sub(const char *val1, const char *val2, char *buffer) +{ char *temp_buffer = alloca(calc_buffer_size); /* intermediate buffer to hold -val2 */ do_negate(val2, temp_buffer); @@ -409,7 +419,8 @@ static void do_sub(const char *val1, const char *val2, char *buffer) { /** * Implements a binary MUL */ -static void do_mul(const char *val1, const char *val2, char *buffer) { +static void do_mul(const char *val1, const char *val2, char *buffer) +{ char *temp_buffer; /* result buffer */ char *neg_val1; /* abs of val1 */ char *neg_val2; /* abs of val2 */ @@ -485,7 +496,8 @@ static void do_mul(const char *val1, const char *val2, char *buffer) { /** * Shift the buffer to left and add a 4 bit digit */ -static void do_push(const char digit, char *buffer) { +static void do_push(const char digit, char *buffer) +{ int counter; for (counter = calc_buffer_size - 2; counter >= 0; counter--) { @@ -499,7 +511,8 @@ static void do_push(const char digit, char *buffer) { * * Note: This is MOST slow */ -static void do_divmod(const char *rDividend, const char *divisor, char *quot, char *rem) { +static void do_divmod(const char *rDividend, const char *divisor, char *quot, char *rem) +{ const char *dividend = rDividend; const char *minus_divisor; char *neg_val1; @@ -589,7 +602,8 @@ end: * * @todo Assertions seems to be wrong */ -static void do_shl(const char *val1, char *buffer, long shift_cnt, int bitsize, unsigned is_signed) { +static void do_shl(const char *val1, char *buffer, long shift_cnt, int bitsize, unsigned is_signed) +{ const char *shl; char shift; char carry = SC_0; @@ -608,7 +622,7 @@ static void do_shl(const char *val1, char *buffer, long shift_cnt, int bitsize, return; } - shift = shift_table[_val(shift_cnt%4)]; /* this is 2 ** (offset % 4) */ + shift = SHIFT(shift_cnt % 4); /* this is 2 ** (offset % 4) */ shift_cnt = shift_cnt / 4; /* shift the single digits some bytes (offset) and some bits (table) @@ -656,7 +670,8 @@ static void do_shl(const char *val1, char *buffer, long shift_cnt, int bitsize, * * @todo Assertions seems to be wrong */ -static void do_shr(const char *val1, char *buffer, long shift_cnt, int bitsize, unsigned is_signed, int signed_shift) { +static void do_shr(const char *val1, char *buffer, long shift_cnt, int bitsize, unsigned is_signed, int signed_shift) +{ const char *shrs; char sign; char msd; @@ -733,7 +748,8 @@ static void do_shr(const char *val1, char *buffer, long shift_cnt, int bitsize, * Implements a Rotate Left. * positive: low-order -> high order, negative other direction */ -static void do_rotl(const char *val1, char *buffer, long offset, int radius, unsigned is_signed) { +static void do_rotl(const char *val1, char *buffer, long offset, int radius, unsigned is_signed) +{ char *temp1, *temp2; temp1 = alloca(calc_buffer_size); temp2 = alloca(calc_buffer_size); @@ -755,18 +771,21 @@ static void do_rotl(const char *val1, char *buffer, long offset, int radius, uns /***************************************************************************** * public functions, declared in strcalc.h *****************************************************************************/ -const void *sc_get_buffer(void) { +const void *sc_get_buffer(void) +{ return (void*)calc_buffer; } -int sc_get_buffer_length(void) { +int sc_get_buffer_length(void) +{ return calc_buffer_size; } /** * Do sign extension if the mode is signed, otherwise to zero extension. */ -void sign_extend(void *buffer, ir_mode *mode) { +void sign_extend(void *buffer, ir_mode *mode) +{ char *calc_buffer = buffer; int bits = get_mode_size_bits(mode) - 1; int nibble = bits >> 2; @@ -794,141 +813,81 @@ void sign_extend(void *buffer, ir_mode *mode) { } } -/* 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; +/* we assume that '0'-'9', 'a'-'z' and 'A'-'Z' are a range. + * The C-standard does theoretically allow otherwise. */ +static inline void check_ascii(void) +{ + /* C standard guarantees that '0'-'9' is a range */ + assert('b'-'a' == 1 + && 'c'-'a' == 2 + && 'd'-'a' == 3 + && 'e'-'a' == 4 + && 'f'-'a' == 5); + assert('B'-'A' == 1 + && 'C'-'A' == 2 + && 'D'-'A' == 3 + && 'E'-'A' == 4 + && 'F'-'A' == 5); +} - char sign = 0; - char *base, *val; +int sc_val_from_str(char sign, unsigned base, const char *str, + unsigned int len, void *buffer) +{ + char *sc_base, *val; - base = alloca(calc_buffer_size); - val = alloca(calc_buffer_size); + assert(sign == -1 || sign == 1); + assert(str != NULL); + assert(len > 0); + check_ascii(); - /* verify valid pointers (not null) */ - assert(str); - /* a string no characters long is an error */ - assert(len); + assert(base > 1 && base <= 16); + sc_base = alloca(calc_buffer_size); + sc_val_from_ulong(base, sc_base); - if (buffer == NULL) buffer = calc_buffer; + val = alloca(calc_buffer_size); + if (buffer == NULL) + buffer = calc_buffer; CLEAR_BUFFER(buffer); - CLEAR_BUFFER(base); CLEAR_BUFFER(val); - /* strip leading spaces */ - while ((len > 0) && (*str == ' ')) { len--; str++; } - - /* if the first two characters are 0x or 0X -> hex - * if the first is a 0 -> oct - * else dec, strip leading -/+ and remember sign - * - * only a + or - sign is no number resulting in an error */ - if (len >= 2) { - switch (str[0]) { - case '0': - if (str[1] == 'x' || str[1] == 'X') { /* hex */ - str += 2; - len -= 2; - base[1] = SC_1; base[0] = SC_0; - } else { /* oct */ - str += 1; - len -= 1; - base[1] = SC_0; base[0] = SC_8; - } - break; - - case '+': - str += 1; - len -= 1; - base[1] = SC_0; base[0] = SC_A; - break; - - case '-': - str += 1; - len -= 1; - sign = 1; - base[1] = SC_0; base[0] = SC_A; - break; - - default: /* dec, else would have begun with 0x or 0 */ - base[1] = SC_0; base[0] = SC_A; - } - } else { /* dec, else would have begun with 0x or 0 */ - base[1] = SC_0; base[0] = SC_A; - } - /* BEGIN string evaluation, from left to right */ while (len > 0) { - switch (*str) { - case 'f': - case 'e': - case 'd': - case 'c': - case 'b': - case 'a': - if (base[0] > SC_A || base[1] > SC_0) { /* (base > 10) */ - val[0] = _digit((*str)-'a'+10); - } - else - fail_char(orig_str, orig_len, *str, str-orig_str+1); - break; - - case 'F': - case 'E': - case 'D': - case 'C': - case 'B': - case 'A': - if (base[0] > SC_A || base[1] > SC_0) { /* (base > 10) */ - val[0] = _digit((*str)-'A'+10); - } - else - fail_char(orig_str, orig_len, *str, str-orig_str+1); - break; - - case '9': - case '8': - if (base[0] > SC_8 || base[1] > SC_0) { /* (base > 8) */ - val[0] = _digit((*str)-'0'); - } - else - fail_char(orig_str, orig_len, *str, str-orig_str+1); - break; - - case '7': - case '6': - case '5': - case '4': - case '3': - case '2': - case '1': - case '0': - val[0] = _digit((*str)-'0'); - break; + char c = *str; + unsigned v; + if (c >= '0' && c <= '9') + v = c - '0'; + else if (c >= 'A' && c <= 'F') + v = c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + v = c - 'a' + 10; + else + return 0; - default: - fail_char(orig_str, orig_len, *str, str-orig_str+1); - } /* switch(*str) */ + if (v >= base) + return 0; + val[0] = v; /* Radix conversion from base b to base B: * (UnUn-1...U1U0)b == ((((Un*b + Un-1)*b + ...)*b + U1)*b + U0)B */ - do_mul(base, calc_buffer, calc_buffer); /* multiply current value with base */ - do_add(val, calc_buffer, calc_buffer); /* add next digit to current value */ + /* multiply current value with base */ + do_mul(sc_base, buffer, buffer); + /* add next digit to current value */ + do_add(val, buffer, buffer); /* get ready for the next letter */ str++; len--; } /* while (len > 0 ) */ - if (sign) - do_negate(calc_buffer, calc_buffer); + if (sign < 0) + do_negate(buffer, buffer); - /* beware: even if hex numbers have no sign, we need sign extension here */ - sign_extend(calc_buffer, mode); + return 1; } -void sc_val_from_long(long value, void *buffer) { +void sc_val_from_long(long value, void *buffer) +{ char *pos; char sign, is_minlong; @@ -961,7 +920,8 @@ void sc_val_from_long(long value, void *buffer) { } } -void sc_val_from_ulong(unsigned long value, void *buffer) { +void sc_val_from_ulong(unsigned long value, void *buffer) +{ unsigned char *pos; if (buffer == NULL) buffer = calc_buffer; @@ -973,7 +933,8 @@ void sc_val_from_ulong(unsigned long value, void *buffer) { } } -long sc_val_to_long(const void *val) { +long sc_val_to_long(const void *val) +{ int i; long l = 0; @@ -983,7 +944,8 @@ long sc_val_to_long(const void *val) { return l; } -void sc_min_from_bits(unsigned int num_bits, unsigned int sign, void *buffer) { +void sc_min_from_bits(unsigned int num_bits, unsigned int sign, void *buffer) +{ char *pos; int i, bits; @@ -1004,7 +966,8 @@ void sc_min_from_bits(unsigned int num_bits, unsigned int sign, void *buffer) { *pos++ = SC_F; } -void sc_max_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) +{ char* pos; int i, bits; @@ -1022,25 +985,27 @@ 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) { +void sc_truncate(unsigned int num_bits, void *buffer) +{ char *cbuffer = buffer; char *pos = cbuffer + (num_bits / 4); char *end = cbuffer + calc_buffer_size; assert(pos < end); - switch(num_bits % 4) { + switch (num_bits % 4) { case 0: /* nothing to do */ break; case 1: *pos++ &= SC_1; break; case 2: *pos++ &= SC_3; break; case 3: *pos++ &= SC_7; break; } - for( ; pos < end; ++pos) + for ( ; pos < end; ++pos) *pos = SC_0; } -int sc_comp(const void* value1, const void* value2) { +int sc_comp(const void* value1, const void* value2) +{ int counter = calc_buffer_size - 1; const char *val1 = (const char *)value1; const char *val2 = (const char *)value2; @@ -1063,7 +1028,8 @@ int sc_comp(const void* value1, const void* value2) { return (val1[counter] > val2[counter]) ? (1) : (-1); } -int sc_get_highest_set_bit(const void *value) { +int sc_get_highest_set_bit(const void *value) +{ const char *val = (const char*)value; int high, counter; @@ -1082,7 +1048,8 @@ int sc_get_highest_set_bit(const void *value) { return high; } -int sc_get_lowest_set_bit(const void *value) { +int sc_get_lowest_set_bit(const void *value) +{ const char *val = (const char*)value; int low, counter; @@ -1115,11 +1082,12 @@ int sc_get_lowest_set_bit(const void *value) { return -1; } -int sc_get_bit_at(const void *value, unsigned pos) { +int sc_get_bit_at(const void *value, unsigned pos) +{ const char *val = value; unsigned nibble = pos >> 2; - return (val[nibble] & shift_table[pos & 3]) != SC_0; + return (val[nibble] & SHIFT(pos & 3)) != SC_0; } void sc_set_bit_at(void *value, unsigned pos) @@ -1127,10 +1095,11 @@ void sc_set_bit_at(void *value, unsigned pos) char *val = value; unsigned nibble = pos >> 2; - val[nibble] |= shift_table[pos & 3]; + val[nibble] |= SHIFT(pos & 3); } -int sc_is_zero(const void *value) { +int sc_is_zero(const void *value) +{ const char* val = (const char *)value; int counter; @@ -1141,15 +1110,18 @@ int sc_is_zero(const void *value) { return 1; } -int sc_is_negative(const void *value) { +int sc_is_negative(const void *value) +{ return do_sign(value) == -1; } -int sc_had_carry(void) { +int sc_had_carry(void) +{ return carry_flag; } -unsigned char sc_sub_bits(const void *value, int len, unsigned byte_ofs) { +unsigned char sc_sub_bits(const void *value, int len, unsigned byte_ofs) +{ const char *val = (const char *)value; int nibble_ofs = 2 * byte_ofs; unsigned char res; @@ -1173,7 +1145,8 @@ unsigned char sc_sub_bits(const void *value, int len, unsigned byte_ofs) { * convert to a string * FIXME: Doesn't check buffer bounds */ -const char *sc_print(const void *value, unsigned bits, enum base_t base, int signed_mode) { +const char *sc_print(const void *value, unsigned bits, enum base_t base, int signed_mode) +{ static const char big_digits[] = "0123456789ABCDEF"; static const char small_digits[] = "0123456789abcdef"; @@ -1316,7 +1289,8 @@ const char *sc_print(const void *value, unsigned bits, enum base_t base, int sig return pos; } -void init_strcalc(int precision) { +void init_strcalc(int precision) +{ if (calc_buffer == NULL) { if (precision <= 0) precision = SC_DEFAULT_PRECISION; @@ -1335,17 +1309,20 @@ void init_strcalc(int precision) { } -void finish_strcalc(void) { +void finish_strcalc(void) +{ free(calc_buffer); calc_buffer = NULL; free(output_buffer); output_buffer = NULL; } -int sc_get_precision(void) { +int sc_get_precision(void) +{ return bit_pattern_size; } -void sc_add(const void *value1, const void *value2, void *buffer) { +void sc_add(const void *value1, const void *value2, void *buffer) +{ CLEAR_BUFFER(calc_buffer); carry_flag = 0; @@ -1361,7 +1338,8 @@ void sc_add(const void *value1, const void *value2, void *buffer) { } } -void sc_sub(const void *value1, const void *value2, void *buffer) { +void sc_sub(const void *value1, const void *value2, void *buffer) +{ CLEAR_BUFFER(calc_buffer); carry_flag = 0; @@ -1377,7 +1355,8 @@ void sc_sub(const void *value1, const void *value2, void *buffer) { } } -void sc_neg(const void *value1, void *buffer) { +void sc_neg(const void *value1, void *buffer) +{ carry_flag = 0; DEBUGPRINTF_COMPUTATION(("- %s ->", sc_print_hex(value1))); @@ -1391,7 +1370,8 @@ void sc_neg(const void *value1, void *buffer) { } } -void sc_and(const void *value1, const void *value2, void *buffer) { +void sc_and(const void *value1, const void *value2, void *buffer) +{ CLEAR_BUFFER(calc_buffer); carry_flag = 0; @@ -1407,7 +1387,25 @@ void sc_and(const void *value1, const void *value2, void *buffer) { } } -void sc_or(const void *value1, const void *value2, void *buffer) { +void sc_andnot(const void *value1, const void *value2, void *buffer) +{ + CLEAR_BUFFER(calc_buffer); + carry_flag = 0; + + DEBUGPRINTF_COMPUTATION(("%s & ", sc_print_hex(value1))); + DEBUGPRINTF_COMPUTATION(("~%s -> ", sc_print_hex(value2))); + + do_bitandnot(value1, value2, calc_buffer); + + DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer))); + + if (buffer != NULL && buffer != calc_buffer) { + memcpy(buffer, calc_buffer, calc_buffer_size); + } +} + +void sc_or(const void *value1, const void *value2, void *buffer) +{ CLEAR_BUFFER(calc_buffer); carry_flag = 0; @@ -1423,7 +1421,8 @@ void sc_or(const void *value1, const void *value2, void *buffer) { } } -void sc_xor(const void *value1, const void *value2, void *buffer) { +void sc_xor(const void *value1, const void *value2, void *buffer) +{ CLEAR_BUFFER(calc_buffer); carry_flag = 0; @@ -1439,7 +1438,8 @@ void sc_xor(const void *value1, const void *value2, void *buffer) { } } -void sc_not(const void *value1, void *buffer) { +void sc_not(const void *value1, void *buffer) +{ CLEAR_BUFFER(calc_buffer); carry_flag = 0; @@ -1454,7 +1454,8 @@ void sc_not(const void *value1, void *buffer) { } } -void sc_mul(const void *value1, const void *value2, void *buffer) { +void sc_mul(const void *value1, const void *value2, void *buffer) +{ CLEAR_BUFFER(calc_buffer); carry_flag = 0; @@ -1470,7 +1471,8 @@ void sc_mul(const void *value1, const void *value2, void *buffer) { } } -void sc_div(const void *value1, const void *value2, void *buffer) { +void sc_div(const void *value1, const void *value2, void *buffer) +{ /* temp buffer holding unused result of divmod */ char *unused_res = alloca(calc_buffer_size); @@ -1489,7 +1491,8 @@ void sc_div(const void *value1, const void *value2, void *buffer) { } } -void sc_mod(const void *value1, const void *value2, void *buffer) { +void sc_mod(const void *value1, const void *value2, void *buffer) +{ /* temp buffer holding unused result of divmod */ char *unused_res = alloca(calc_buffer_size); @@ -1508,7 +1511,8 @@ void sc_mod(const void *value1, const void *value2, void *buffer) { } } -void sc_divmod(const void *value1, const void *value2, void *div_buffer, void *mod_buffer) { +void sc_divmod(const void *value1, const void *value2, void *div_buffer, void *mod_buffer) +{ CLEAR_BUFFER(calc_buffer); carry_flag = 0; @@ -1521,7 +1525,8 @@ void sc_divmod(const void *value1, const void *value2, void *div_buffer, void *m } -void sc_shlI(const void *val1, long shift_cnt, int bitsize, int sign, void *buffer) { +void sc_shlI(const void *val1, long shift_cnt, int bitsize, int sign, void *buffer) +{ carry_flag = 0; DEBUGPRINTF_COMPUTATION(("%s << %ld ", sc_print_hex(value1), shift_cnt)); @@ -1534,13 +1539,15 @@ void sc_shlI(const void *val1, long shift_cnt, int bitsize, int sign, void *buff } } -void sc_shl(const void *val1, const void *val2, int bitsize, int sign, void *buffer) { +void sc_shl(const void *val1, const void *val2, int bitsize, int sign, void *buffer) +{ long offset = sc_val_to_long(val2); sc_shlI(val1, offset, bitsize, sign, buffer); } -void sc_shrI(const void *val1, long shift_cnt, int bitsize, int sign, void *buffer) { +void sc_shrI(const void *val1, long shift_cnt, int bitsize, int sign, void *buffer) +{ carry_flag = 0; DEBUGPRINTF_COMPUTATION(("%s >>u %ld ", sc_print_hex(value1), shift_cnt)); @@ -1553,13 +1560,15 @@ void sc_shrI(const void *val1, long shift_cnt, int bitsize, int sign, void *buff } } -void sc_shr(const void *val1, const void *val2, int bitsize, int sign, void *buffer) { +void sc_shr(const void *val1, const void *val2, int bitsize, int sign, void *buffer) +{ long shift_cnt = sc_val_to_long(val2); sc_shrI(val1, shift_cnt, bitsize, sign, buffer); } -void sc_shrs(const void *val1, const void *val2, int bitsize, int sign, void *buffer) { +void sc_shrs(const void *val1, const void *val2, int bitsize, int sign, void *buffer) +{ long offset = sc_val_to_long(val2); carry_flag = 0; @@ -1574,7 +1583,8 @@ void sc_shrs(const void *val1, const void *val2, int bitsize, int sign, void *bu } } -void sc_rotl(const void *val1, const void *val2, int bitsize, int sign, void *buffer) { +void sc_rotl(const void *val1, const void *val2, int bitsize, int sign, void *buffer) +{ long offset = sc_val_to_long(val2); carry_flag = 0; @@ -1589,7 +1599,8 @@ void sc_rotl(const void *val1, const void *val2, int bitsize, int sign, void *bu } } -void sc_zero(void *buffer) { +void sc_zero(void *buffer) +{ if (buffer == NULL) buffer = calc_buffer; CLEAR_BUFFER(buffer);