X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=ir%2Ftv%2Fstrcalc.c;h=98e41ce4216ed69c585d23724886c9785aa1b25e;hb=1ce363f80e6a204d4011f85813362d9bd1d0e7e4;hp=10bf88572436c7144b1d53438871dc5dfa9fa855;hpb=ab1b5847c0167c06091c30c2a6ea4d1d94b7c40d;p=libfirm diff --git a/ir/tv/strcalc.c b/ir/tv/strcalc.c index 10bf88572..98e41ce42 100644 --- a/ir/tv/strcalc.c +++ b/ir/tv/strcalc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -746,7 +746,7 @@ end: * * @todo Assertions seems to be wrong */ -static void _shl(const char *val1, char *buffer, long offset, int radius, unsigned is_signed) { +static void _shl(const char *val1, char *buffer, long shift_cnt, int bitsize, unsigned is_signed) { const char *shl; char shift; char carry = SC_0; @@ -754,52 +754,52 @@ static void _shl(const char *val1, char *buffer, long offset, int radius, unsign int counter; int bitoffset = 0; - assert((offset >= 0) || (0 && "negative leftshift")); + assert((shift_cnt >= 0) || (0 && "negative leftshift")); assert(((_sign(val1) != -1) || is_signed) || (0 && "unsigned mode and negative value")); - assert(((!_bitisset(val1[(radius-1)/4], (radius-1)%4)) || !is_signed || (_sign(val1) == -1)) || (0 && "value is positive, should be negative")); - assert(((_bitisset(val1[(radius-1)/4], (radius-1)%4)) || !is_signed || (_sign(val1) == 1)) || (0 && "value is negative, should be positive")); + assert(((!_bitisset(val1[(bitsize-1)/4], (bitsize-1)%4)) || !is_signed || (_sign(val1) == -1)) || (0 && "value is positive, should be negative")); + assert(((_bitisset(val1[(bitsize-1)/4], (bitsize-1)%4)) || !is_signed || (_sign(val1) == 1)) || (0 && "value is negative, should be positive")); /* if shifting far enough the result is zero */ - if (offset >= radius) { + if (shift_cnt >= bitsize) { memset(buffer, SC_0, calc_buffer_size); return; } - shift = shift_table[_val(offset%4)]; /* this is 2 ** (offset % 4) */ - offset = offset / 4; + shift = shift_table[_val(shift_cnt%4)]; /* this is 2 ** (offset % 4) */ + shift_cnt = shift_cnt / 4; /* shift the single digits some bytes (offset) and some bits (table) * to the left */ - for (counter = 0; counter < radius/4 - offset; counter++) { + for (counter = 0; counter < bitsize/4 - shift_cnt; counter++) { shl = mul_table[_val(val1[counter])][_val(shift)]; - buffer[counter + offset] = or_table[_val(shl[0])][_val(carry)]; + buffer[counter + shift_cnt] = or_table[_val(shl[0])][_val(carry)]; carry = shl[1]; } - if (radius%4 > 0) { + if (bitsize%4 > 0) { shl = mul_table[_val(val1[counter])][_val(shift)]; - buffer[counter + offset] = or_table[_val(shl[0])][_val(carry)]; + buffer[counter + shift_cnt] = or_table[_val(shl[0])][_val(carry)]; bitoffset = counter; } else { bitoffset = counter - 1; } /* fill with zeroes */ - for (counter = 0; counter < offset; counter++) + for (counter = 0; counter < shift_cnt; counter++) buffer[counter] = SC_0; /* if the mode was signed, change sign when the mode's msb is now 1 */ - offset = bitoffset + offset; - bitoffset = (radius-1) % 4; - if (is_signed && _bitisset(buffer[offset], bitoffset)) { + shift_cnt = bitoffset + shift_cnt; + bitoffset = (bitsize-1) % 4; + if (is_signed && _bitisset(buffer[shift_cnt], bitoffset)) { /* this sets the upper bits of the leftmost digit */ - buffer[offset] = or_table[_val(buffer[offset])][_val(min_digit[bitoffset])]; - for (counter = offset+1; counter < calc_buffer_size; counter++) { + buffer[shift_cnt] = or_table[_val(buffer[shift_cnt])][_val(min_digit[bitoffset])]; + for (counter = shift_cnt+1; counter < calc_buffer_size; counter++) { buffer[counter] = SC_F; } - } else if (is_signed && !_bitisset(buffer[offset], bitoffset)) { + } else if (is_signed && !_bitisset(buffer[shift_cnt], bitoffset)) { /* 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++) { + buffer[shift_cnt] = and_table[_val(buffer[shift_cnt])][_val(max_digit[bitoffset])]; + for (counter = shift_cnt+1; counter < calc_buffer_size; counter++) { buffer[counter] = SC_0; } } @@ -809,26 +809,28 @@ static void _shl(const char *val1, char *buffer, long offset, int radius, unsign * Implements a Shift Right, which can either preserve the sign bit * or not. * + * @param bitsize bitsize of the value to be shifted + * * @todo Assertions seems to be wrong */ -static void _shr(const char *val1, char *buffer, long offset, int radius, unsigned is_signed, int signed_shift) { +static void _shr(const char *val1, char *buffer, long shift_cnt, int bitsize, unsigned is_signed, int signed_shift) { const char *shrs; char sign; char msd; - int shift; + int shift_mod, shift_nib; int counter; int bitoffset = 0; - assert((offset >= 0) || (0 && "negative rightshift")); - assert(((!_bitisset(val1[(radius-1)/4], (radius-1)%4)) || !is_signed || (_sign(val1) == -1)) || (0 && "value is positive, should be negative")); - assert(((_bitisset(val1[(radius-1)/4], (radius-1)%4)) || !is_signed || (_sign(val1) == 1)) || (0 && "value is negative, should be positive")); + assert((shift_cnt >= 0) || (0 && "negative rightshift")); + assert(((!_bitisset(val1[(bitsize-1)/4], (bitsize-1)%4)) || !is_signed || (_sign(val1) == -1)) || (0 && "value is positive, should be negative")); + assert(((_bitisset(val1[(bitsize-1)/4], (bitsize-1)%4)) || !is_signed || (_sign(val1) == 1)) || (0 && "value is negative, should be positive")); - sign = ((signed_shift) && (_sign(val1) == -1))?(SC_F):(SC_0); + sign = signed_shift && _bit(val1, bitsize - 1) ? SC_F : SC_0; /* if shifting far enough the result is either 0 or -1 */ - if (offset >= radius) { + if (shift_cnt >= bitsize) { if (!sc_is_zero(val1)) { carry_flag = 1; } @@ -836,50 +838,51 @@ static void _shr(const char *val1, char *buffer, long offset, int radius, unsign return; } - shift = offset % 4; - offset = offset / 4; + shift_mod = shift_cnt & 3; + shift_nib = shift_cnt >> 2; /* check if any bits are lost, and set carry_flag if so */ - for (counter = 0; counter < offset; counter++) { + for (counter = 0; counter < shift_nib; ++counter) { if (val1[counter] != 0) { carry_flag = 1; break; } } - if ((_val(val1[counter]) & ((1< 0) { - buffer[counter] = shrs_table[_val(val1[offset])][shift][0]; + if ((bitsize >> 2) > shift_nib) { + buffer[counter] = shrs_table[_val(val1[shift_nib])][shift_mod][0]; counter = 1; } - for (; counter < radius/4 - offset; counter++) { - shrs = shrs_table[_val(val1[counter + offset])][shift]; + for (; counter < bitsize/4 - shift_nib; counter++) { + shrs = shrs_table[_val(val1[counter + shift_nib])][shift_mod]; buffer[counter] = shrs[0]; buffer[counter-1] = or_table[_val(buffer[counter-1])][_val(shrs[1])]; } /* the last digit is special in regard of signed/unsigned shift */ - bitoffset = radius%4; - msd = (radius/4 0) buffer[counter - 1] = or_table[_val(buffer[counter-1])][_val(shrs[1])]; + if (counter > 0) + buffer[counter - 1] = or_table[_val(buffer[counter-1])][_val(shrs[1])]; /* fill with SC_F or SC_0 depending on sign */ for (counter++; counter < calc_buffer_size; counter++) { @@ -1180,6 +1183,24 @@ 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 *cbuffer = buffer; + char *pos = cbuffer + (num_bits / 4); + char *end = cbuffer + 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; @@ -1225,19 +1246,31 @@ int sc_get_highest_set_bit(const void *value) { int sc_get_lowest_set_bit(const void *value) { const char *val = (const char*)value; int low, counter; - char sign; - sign = (_sign(val)==1)?(SC_0):(SC_F); low = 0; - for (counter = 0; counter < calc_buffer_size; counter++) { - if (val[counter] == SC_0) + switch (val[counter]) { + case SC_1: + case SC_3: + case SC_5: + case SC_7: + case SC_9: + case SC_B: + case SC_D: + case SC_F: + return low; + case SC_2: + case SC_6: + case SC_A: + case SC_E: + return low + 1; + case SC_4: + case SC_C: + return low + 2; + case SC_8: + return low + 3; + default: low += 4; - else { - if (val[counter] < SC_2) return low; - else if (val[counter] < SC_4) return low + 1; - else if (val[counter] < SC_8) return low + 2; - else return low + 3; } } return -1; @@ -1276,8 +1309,8 @@ 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) { - res &= 0xFF >> (8*byte_ofs - len); + if (len - 8 * byte_ofs < 8) { + res &= (1 << (len - 8 * byte_ofs)) - 1; } return res; } @@ -1491,7 +1524,6 @@ void sc_sub(const void *value1, const void *value2, void *buffer) { } void sc_neg(const void *value1, void *buffer) { - CLEAR_BUFFER(calc_buffer); carry_flag = 0; DEBUGPRINTF_COMPUTATION(("- %s ->", sc_print_hex(value1))); @@ -1622,14 +1654,24 @@ 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) { + CLEAR_BUFFER(calc_buffer); + carry_flag = 0; -void sc_shl(const void *val1, const void *val2, int radius, int sign, void *buffer) { - long offset = sc_val_to_long(val2); + DEBUGPRINTF_COMPUTATION(("%s %% ", sc_print_hex(value1))); + DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2))); + + _divmod(value1, value2, div_buffer, mod_buffer); + DEBUGPRINTF_COMPUTATION(("%s:%s\n", sc_print_hex(div_buffer), sc_print_hex(mod_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), offset)); - _shl(val1, calc_buffer, offset, radius, sign); + DEBUGPRINTF_COMPUTATION(("%s << %ld ", sc_print_hex(value1), shift_cnt)); + _shl(val1, calc_buffer, shift_cnt, bitsize, sign); DEBUGPRINTF_COMPUTATION(("-> %s\n", sc_print_hex(calc_buffer))); @@ -1638,13 +1680,17 @@ void sc_shl(const void *val1, const void *val2, int radius, int sign, void *buff } } -void sc_shr(const void *val1, const void *val2, int radius, 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) { carry_flag = 0; - DEBUGPRINTF_COMPUTATION(("%s >>u %ld ", sc_print_hex(value1), offset)); - _shr(val1, calc_buffer, offset, radius, sign, 0); + DEBUGPRINTF_COMPUTATION(("%s >>u %ld ", sc_print_hex(value1), shift_cnt)); + _shr(val1, calc_buffer, shift_cnt, bitsize, sign, 0); DEBUGPRINTF_COMPUTATION(("-> %s\n", sc_print_hex(calc_buffer))); @@ -1653,13 +1699,19 @@ void sc_shr(const void *val1, const void *val2, int radius, int sign, void *buff } } -void sc_shrs(const void *val1, const void *val2, int radius, 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) { long offset = sc_val_to_long(val2); carry_flag = 0; DEBUGPRINTF_COMPUTATION(("%s >>s %ld ", sc_print_hex(value1), offset)); - _shr(val1, calc_buffer, offset, radius, sign, 1); + _shr(val1, calc_buffer, offset, bitsize, sign, 1); DEBUGPRINTF_COMPUTATION(("-> %s\n", sc_print_hex(calc_buffer))); @@ -1668,13 +1720,13 @@ void sc_shrs(const void *val1, const void *val2, int radius, int sign, void *buf } } -void sc_rot(const void *val1, const void *val2, int radius, int sign, void *buffer) { +void sc_rot(const void *val1, const void *val2, int bitsize, int sign, void *buffer) { long offset = sc_val_to_long(val2); carry_flag = 0; DEBUGPRINTF_COMPUTATION(("%s <<>> %ld ", sc_print_hex(value1), offset)); - _rot(val1, calc_buffer, offset, radius, sign); + _rot(val1, calc_buffer, offset, bitsize, sign); DEBUGPRINTF_COMPUTATION(("-> %s\n", sc_print_hex(calc_buffer))); @@ -1682,3 +1734,10 @@ void sc_rot(const void *val1, const void *val2, int radius, int sign, void *buff memmove(buffer, calc_buffer, calc_buffer_size); } } + +void sc_zero(void *buffer) { + if (buffer == NULL) + buffer = calc_buffer; + CLEAR_BUFFER(buffer); + carry_flag = 0; +}