Commit 9ea59941 authored by Matthias Braun's avatar Matthias Braun
Browse files

strcalc: cleanup sign/zero extension code

parent 1e94ae22
......@@ -64,11 +64,6 @@ void sc_zero(sc_word *buffer)
memset(buffer, 0, sizeof(buffer[0]) * calc_buffer_size);
}
static sc_word zex_digit(unsigned x)
{
return (1u << (x+1)) - 1;
}
static sc_word sex_digit(unsigned x)
{
return (SC_MASK << (x+1)) & SC_MASK;
......@@ -119,8 +114,7 @@ void sc_andnot(const sc_word *val1, const sc_word *val2, sc_word *buffer)
*/
static void sc_inc(const sc_word *val, sc_word *buffer)
{
unsigned counter;
for (counter = 0; counter < calc_buffer_size; ++counter) {
for (unsigned counter = 0; counter < calc_buffer_size; ++counter) {
sc_word v = val[counter];
if (v < SC_MASK) {
buffer[counter] = v+1;
......@@ -466,30 +460,30 @@ unsigned sc_get_buffer_length(void)
return calc_buffer_size;
}
void sign_extend(sc_word *buffer, unsigned from_bits, bool is_signed)
void sc_zero_extend(sc_word *buffer, unsigned from_bits)
{
unsigned bits = from_bits - 1;
unsigned nibble = bits / SC_BITS;
if (is_signed) {
sc_word max = max_digit(bits % SC_BITS);
if (buffer[nibble] > max) {
/* sign bit is set, we need sign expansion */
for (unsigned i = nibble + 1; i < calc_buffer_size; ++i)
buffer[i] = SC_MASK;
buffer[nibble] |= sex_digit(bits % SC_BITS);
} else {
/* set all bits to zero */
for (unsigned i = nibble + 1; i < calc_buffer_size; ++i)
buffer[i] = 0;
buffer[nibble] &= zex_digit(bits % SC_BITS);
}
unsigned bit = from_bits % SC_BITS;
unsigned word = from_bits / SC_BITS;
if (bit > 0) {
memset(&buffer[word+1], 0, calc_buffer_size-(word+1));
buffer[word] &= max_digit(bit);
} else {
memset(&buffer[word], 0, calc_buffer_size-word);
}
}
void sc_sign_extend(sc_word *buffer, unsigned from_bits)
{
unsigned bits = from_bits - 1;
bool sign_bit = sc_get_bit_at(buffer, bits);
if (sign_bit) {
/* sign bit is set, we need sign extension */
unsigned word = bits / SC_BITS;
for (unsigned i = word + 1; i < calc_buffer_size; ++i)
buffer[i] = SC_MASK;
buffer[word] |= sex_digit(bits % SC_BITS);
} else {
/* do zero extension */
for (unsigned i = nibble + 1; i < calc_buffer_size; ++i)
buffer[i] = 0;
buffer[nibble] &= zex_digit(bits % SC_BITS);
sc_zero_extend(buffer, from_bits);
}
}
......@@ -648,25 +642,6 @@ void sc_max_from_bits(unsigned num_bits, bool sign, sc_word *buffer)
*pos++ = 0;
}
void sc_truncate(unsigned num_bits, sc_word *buffer)
{
sc_word *cbuffer = buffer;
sc_word *pos = cbuffer + (num_bits / SC_BITS);
sc_word *end = cbuffer + calc_buffer_size;
assert(pos < end);
switch (num_bits % SC_BITS) {
case 0: /* nothing to do */ break;
case 1: *pos++ &= 1; break;
case 2: *pos++ &= 3; break;
case 3: *pos++ &= 7; break;
}
for ( ; pos < end; ++pos)
*pos = 0;
}
ir_relation sc_comp(const sc_word* const val1, const sc_word* const val2)
{
/* compare signs first:
......@@ -925,7 +900,7 @@ char *sc_print_buf(char *buf, size_t buf_len, const sc_word *value,
/* last nibble must be masked */
if (bits % SC_BITS) {
sc_word mask = zex_digit((bits % SC_BITS) - 1);
sc_word mask = max_digit(bits % SC_BITS);
sc_word x = value[counter++] & mask;
*(--pos) = digits[x];
assert(pos >= buf);
......@@ -952,7 +927,7 @@ char *sc_print_buf(char *buf, size_t buf_len, const sc_word *value,
/* last nibble must be masked */
if (bits % SC_BITS) {
sc_word mask = zex_digit((bits % SC_BITS) - 1);
sc_word mask = max_digit(bits % SC_BITS);
sc_word x = value[counter++] & mask;
pos -= SC_BITS;
......@@ -996,7 +971,7 @@ char *sc_print_buf(char *buf, size_t buf_len, const sc_word *value,
/* last nibble must be masked */
if (bits % SC_BITS) {
sc_word mask = zex_digit((bits % SC_BITS) - 1);
sc_word mask = max_digit(bits % SC_BITS);
div1_res[counter] = p[counter] & mask;
++counter;
}
......
......@@ -150,7 +150,9 @@ void sc_zero(sc_word *buffer);
const sc_word *sc_get_buffer(void);
unsigned sc_get_buffer_length(void);
void sign_extend(sc_word *buffer, unsigned from_bits, bool is_signed);
void sc_sign_extend(sc_word *buffer, unsigned from_bits);
void sc_zero_extend(sc_word *buffer, unsigned from_bits);
/**
* create an value form a string representation
......@@ -191,9 +193,6 @@ uint64_t sc_val_to_uint64(const sc_word *val);
void sc_min_from_bits(unsigned num_bits, bool sign, sc_word *buffer);
void sc_max_from_bits(unsigned num_bits, bool sign, sc_word *buffer);
/** truncates a value to lowest @p num_bits bits */
void sc_truncate(unsigned num_bits, sc_word *buffer);
/**
* Compares val1 and val2
*/
......
......@@ -111,8 +111,11 @@ static ir_tarval *get_tarval(const void *value, size_t length, ir_mode *mode)
char *temp = ALLOCAN(char, length);
memcpy(temp, value, length);
if (get_mode_arithmetic(mode) == irma_twos_complement) {
sign_extend((sc_word*)temp, get_mode_size_bits(mode),
mode_is_signed(mode));
if (mode_is_signed(mode)) {
sc_sign_extend((sc_word*)temp, get_mode_size_bits(mode));
} else {
sc_zero_extend((sc_word*)temp, get_mode_size_bits(mode));
}
}
tv.value = INSERT_VALUE(temp, length);
} else {
......@@ -132,9 +135,13 @@ static ir_tarval *get_tarval_overflow(const void *value, size_t length,
/* addresses always wrap around */
sc_word *temp = ALLOCAN(sc_word, sc_get_buffer_length());
memcpy(temp, value, sc_get_buffer_length());
sc_truncate(get_mode_size_bits(mode), temp);
unsigned bits = get_mode_size_bits(mode);
/* the sc_ module expects that all bits are set ... */
sign_extend(temp, get_mode_size_bits(mode), mode_is_signed(mode));
if (mode_is_signed(mode)) {
sc_sign_extend(temp, bits);
} else {
sc_zero_extend(temp, bits);
}
return get_tarval(temp, length, mode);
}
......@@ -146,9 +153,13 @@ static ir_tarval *get_tarval_overflow(const void *value, size_t length,
case TV_OVERFLOW_WRAP: {
sc_word *temp = ALLOCAN(sc_word, sc_get_buffer_length());
memcpy(temp, value, sc_get_buffer_length());
sc_truncate(get_mode_size_bits(mode), temp);
unsigned bits = get_mode_size_bits(mode);
/* the sc_ module expects that all bits are set ... */
sign_extend(temp, get_mode_size_bits(mode), mode_is_signed(mode));
if (mode_is_signed(mode)) {
sc_sign_extend(temp, bits);
} else {
sc_zero_extend(temp, bits);
}
return get_tarval(temp, length, mode);
}
case TV_OVERFLOW_BAD:
......@@ -164,7 +175,6 @@ static ir_tarval *get_tarval_overflow(const void *value, size_t length,
case TV_OVERFLOW_WRAP: {
sc_word *temp = ALLOCAN(sc_word, sc_get_buffer_length());
memcpy(temp, value, sc_get_buffer_length());
sc_truncate(get_mode_size_bits(mode), temp);
return get_tarval(temp, length, mode);
}
case TV_OVERFLOW_BAD:
......@@ -367,7 +377,7 @@ int tarval_is_long(ir_tarval *tv)
if (mode_is_signed(mode)) {
sc_word *min = ALLOCAN(sc_word, sc_get_buffer_length());
sc_min_from_bits(long_bits, true, min);
sign_extend(min, long_bits, true);
sc_sign_extend(min, long_bits);
if (sc_comp(tv->value, min) == ir_relation_less)
return false;
}
......@@ -820,8 +830,12 @@ ir_tarval *tarval_convert_to(ir_tarval *src, ir_mode *dst_mode)
if (get_mode_sort(dst_mode) == irms_int_number) {
sc_word *buffer = ALLOCAN(sc_word, sc_get_buffer_length());
memcpy(buffer, src->value, sc_get_buffer_length());
sign_extend(buffer, get_mode_size_bits(src->mode),
mode_is_signed(src->mode));
unsigned bits = get_mode_size_bits(src->mode);
if (mode_is_signed(src->mode)) {
sc_sign_extend(buffer, bits);
} else {
sc_zero_extend(buffer, bits);
}
return get_tarval_overflow(buffer, src->length, dst_mode);
}
break;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment