From: Michael Beck Date: Wed, 9 Apr 2003 11:24:07 +0000 (+0000) Subject: Added decimal/octal/binary output for integer values X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=54ce4eb3599f32b1dfffeaf0dd071f1907d2b898;p=libfirm Added decimal/octal/binary output for integer values [r1046] --- diff --git a/ir/tv/strcalc.c b/ir/tv/strcalc.c index 1c5514e0b..fa054f66d 100644 --- a/ir/tv/strcalc.c +++ b/ir/tv/strcalc.c @@ -14,9 +14,9 @@ #include /* output for error messages */ #include -/***************************************************************************** +/* * local definitions and macros - *****************************************************************************/ + */ #define BIT_PATTERN_SIZE (8 * BIGGEST_INTEGER_SIZE_IN_BYTES) #define CALC_BUFFER_SIZE (4 * BIGGEST_INTEGER_SIZE_IN_BYTES) #define MAX_VALUE_SIZE (2 * BIGGEST_INTEGER_SIZE_IN_BYTES) @@ -28,15 +28,22 @@ #define fail_char(a, b, c, d) _fail_char((a), (b), (c), (d), __FILE__, __LINE__) +/* shortcut output for debugging only, gices always full precisition */ +#define sc_print_hex(a) sc_print((a), 0, SC_HEX) +#define sc_print_dec(a) sc_print((a), 0, SC_DEC) +#define sc_print_oct(a) sc_print((a), 0, SC_OCT) +#define sc_print_bin(a) sc_print((a), 0, SC_BIN) + + #if 0 # define DEBUGPRINTF(x) printf x #else # define DEBUGPRINTF(x) ((void)0) #endif -/***************************************************************************** +/* * private variables - *****************************************************************************/ + */ static char calc_buffer[CALC_BUFFER_SIZE]; /* buffer holding all results */ @@ -378,6 +385,13 @@ static char const shrs_table[16][4][2] = { { {SC_E, SC_0}, {SC_7, SC_0}, {SC_3, SC_8}, {SC_1, SC_C} }, { {SC_F, SC_0}, {SC_7, SC_8}, {SC_3, SC_C}, {SC_1, SC_E} } }; + +/* for converting to binary string */ +static const char *binary_table[16] = { + "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", + "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" +}; + /***************************************************************************** * private functions *****************************************************************************/ @@ -580,7 +594,8 @@ static void _divmod(const char *dividend, const char *divisor, char *quot, char memset(rem, SC_0, CALC_BUFFER_SIZE); /* if the dividend is zero result is zero (quot is zero)*/ - if (sc_comp(dividend, quot) == 0) return; + if (sc_comp(dividend, quot) == 0) + return; /* if the divisor is zero this won't work (quot is zero) */ if (sc_comp(divisor, quot) == 0) assert(0 && "quotision by zero!"); @@ -1213,34 +1228,123 @@ unsigned char sc_sub_bits(const void *value, int len, unsigned byte_ofs) return res; } -const char *sc_print(const void *value, unsigned base) +/* + * convert to a string + */ +const char *sc_print(const void *value, unsigned bits, enum base_t base) { - int counter; + char base_val[CALC_BUFFER_SIZE]; + char div1_res[CALC_BUFFER_SIZE]; + char div2_res[CALC_BUFFER_SIZE]; + char rem_res[CALC_BUFFER_SIZE]; + int counter, nibbles, i; + char x; const char *val = (const char *)value; + const char *p; + char *m, *n, *t; char *pos; static char *buf = NULL; - if (buf != NULL) free(buf); - buf = malloc(BIT_PATTERN_SIZE); + if (! buf) { + /* TODO: this buffer could be allocated in the initialising phase too */ + buf = malloc(BIT_PATTERN_SIZE + 1); + if (! buf) + return NULL; + } - pos = buf + BIT_PATTERN_SIZE - 1; + pos = buf + BIT_PATTERN_SIZE; *pos = '\0'; - switch (base) - { - case SC_HEX: - for (counter = 0; counter < MAX_VALUE_SIZE; counter++) - { - if (val[counter] < SC_A) - *(--pos) = val[counter] + '0'; - else - *(--pos) = val[counter] + 'a' - 10; - } - break; + /* special case */ + if (bits == 0) + bits = BIT_PATTERN_SIZE; - default: - assert(0); - } + nibbles = bits >> 2; + switch (base) { + + case SC_HEX: + for (counter = 0; counter < nibbles; ++counter) + *(--pos) = "0123456789abcdef"[_val(val[counter])]; + + /* last nibble must be masked */ + if (bits & 3) { + x = and_table[_val(val[++counter])][bits & 3]; + *(--pos) = "0123456789abcdef"[_val(x)]; + } + + /* now kill zeros */ + for (; counter > 1; --counter, ++pos) + if (pos[0] != '0') + break; + break; + + case SC_BIN: + for (counter = 0; counter < nibbles; ++counter) { + pos -= 4; + p = binary_table[_val(val[counter])]; + pos[0] = p[0]; + pos[1] = p[1]; + pos[2] = p[2]; + pos[3] = p[3]; + } + + /* last nibble must be masked */ + if (bits & 3) { + x = and_table[_val(val[++counter])][bits & 3]; + + pos -= 4; + p = binary_table[_val(x)]; + pos[0] = p[0]; + pos[1] = p[1]; + pos[2] = p[2]; + pos[3] = p[3]; + } + + /* now kill zeros */ + for (counter <<= 2; counter > 1; --counter, ++pos) + if (pos[0] != '0') + break; + break; + + case SC_DEC: + case SC_OCT: + memset(base_val, SC_0, CALC_BUFFER_SIZE); + base_val[0] = base == SC_DEC ? SC_A : SC_8; + + /* transfer data into oscilating buffers */ + memset(div1_res, SC_0, CALC_BUFFER_SIZE); + for (counter = 0; counter < nibbles; ++counter) + div1_res[counter] = val[counter]; + + /* last nibble must be masked */ + if (bits & 3) { + ++counter; + + div1_res[counter] = and_table[_val(val[counter])][bits & 3]; + } + + m = div1_res; + n = div2_res; + for (;;) { + _divmod(m, base_val, n, rem_res); + t = m; + m = n; + n = t; + *(--pos) = "0123456789abcdef"[_val(rem_res[0])]; + + x = 0; + for (i = 0; i < sizeof(div1_res); ++i) + x |= _val(m[i]); + + if (x == 0) + break; + } + break; + + default: + assert(0); + return NULL; +} return pos; } diff --git a/ir/tv/strcalc.h b/ir/tv/strcalc.h index c614dba88..d73bfea27 100644 --- a/ir/tv/strcalc.h +++ b/ir/tv/strcalc.h @@ -43,33 +43,39 @@ enum { SC_F, }; +/** + * Possible operations on integer values. + */ enum { - SC_ADD = 0, - SC_SUB, - SC_NEG, - SC_MUL, - SC_DIV, - SC_MOD, - SC_SHL, - SC_SHR, - SC_SHRS, - SC_ROT, - SC_AND, - SC_OR, - SC_NOT, - SC_XOR, + SC_ADD = 0, /**< Addition */ + SC_SUB, /**< Substraction */ + SC_NEG, /**< Unary Minus */ + SC_MUL, /**< Multiplication */ + SC_DIV, /**< Integer Division (with rounding toward zero ?) */ + SC_MOD, /**< Devision Remainder */ + SC_SHL, /**< Left Shift */ + SC_SHR, /**< Logical (unsigned) Right Shift */ + SC_SHRS, /**< Arithmetic (signed) Right Shift */ + SC_ROT, /**< Rotation (both directions) */ + SC_AND, /**< Bitwise And */ + SC_OR, /**< Bitwise Or */ + SC_NOT, /**< Bitwise Not */ + SC_XOR, /**< Bitwise Exclusive Or */ }; -enum { - SC_HEX, - SC_DEC, - SC_OKT, - SC_BIN, +/** + * The output mode for ntger values. + */ +enum base_t { + SC_HEX, /**< hexadecimal output */ + SC_DEC, /**< decimal output */ + SC_OCT, /**< octal output */ + SC_BIN, /**< binary output */ }; -/***************************************************************************** +/* * definitions and macros - *****************************************************************************/ + */ #define sc_add(a, b) sc_calc((a), (b), SC_ADD) #define sc_sub(a, b) sc_calc((a), (b), SC_SUB) #define sc_neg(a) sc_calc((a), NULL, SC_NEG) @@ -85,13 +91,9 @@ enum { #define sc_shrs(a, b, c, d) sc_bitcalc((a), (b), (c), (d), SC_SHRS) #define sc_rot(a, b, c, d) sc_bitcalc((a), (b), (c), (d), SC_ROT) -#define sc_print_hex(a) sc_print((a), SC_HEX) -#define sc_print_dec(a) sc_print((a), SC_DEC) -#define sc_print_okt(a) sc_print((a), SC_OKT) -#define sc_print_bin(a) sc_print((a), SC_BIN) -/***************************************************************************** +/* * function declarations - *****************************************************************************/ + */ const void *sc_get_buffer(void); const int sc_get_buffer_length(void); @@ -107,6 +109,13 @@ int sc_comp(const void *val1, const void *val2); unsigned char sc_sub_bits(const void *val, int len, unsigned byte_ofs); -const char *sc_print(const void *val1, unsigned base); +/** + * Converts a tarval into a string. + * + * @param val1 the value pointer + * @param bits number of valid bits in this value + * @param base output base + */ +const char *sc_print(const void *val1, unsigned bits, enum base_t base); #endif /* _STRCALC_H_ */ diff --git a/ir/tv/tv.c b/ir/tv/tv.c index 59829f5bd..41960b004 100644 --- a/ir/tv/tv.c +++ b/ir/tv/tv.c @@ -896,7 +896,6 @@ int tarval_print(XP_PAR1, const xprintf_info *info ATTRIBUTE((unused)), XP_PARN) ANNOUNCE(); tarval *tv; const char *str; - int offset; char buf[100]; tv = XP_GETARG(tarval *, 0); @@ -904,9 +903,8 @@ int tarval_print(XP_PAR1, const xprintf_info *info ATTRIBUTE((unused)), XP_PARN) { case int_number: case character: - offset = 16 - (get_mode_size_bits(tv->mode)/4); - str = sc_print_hex(tv->value); - return XPF1R("0x%s", str + offset); + str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_DEC); + return XPF1R("%s", str); case float_number: return XPF1R("%s", fc_print_dec(tv->value, buf, sizeof(buf)));