From 4ca2b9085b12d5dac2d975a830f7e74148e67e78 Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Wed, 18 Oct 2006 14:42:38 +0000 Subject: [PATCH] sign_extend() did NOT expect all upper bits cleared but clear it sign_extend does zero extension for unsigned integer modes [r8359] --- ir/tv/strcalc.c | 30 ++++++++++++++++++++---------- ir/tv/tv.c | 5 ++++- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/ir/tv/strcalc.c b/ir/tv/strcalc.c index ec802385e..6e45a26b4 100644 --- a/ir/tv/strcalc.c +++ b/ir/tv/strcalc.c @@ -78,6 +78,7 @@ static int carry_flag; /**< some computation set the carry_flag: and often defined in other ways! */ static const char sex_digit[4] = { SC_E, SC_C, SC_8, SC_0 }; +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 }; @@ -959,23 +960,32 @@ int sc_get_buffer_length(void) } /** - * Do sign extension if the mode is signed, expects all upper bits - * cleared. + * Do sign extension if the mode is signed, otherwise to zero extension. */ 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; + int bits = get_mode_size_bits(mode) - 1; + int nibble = bits >> 2; + int max = max_digit[bits & 3]; + int i; - if (calc_buffer[ofs] > max) { + if (mode_is_signed(mode)) { + if (calc_buffer[nibble] > max) { /* sign bit is set, we need sign expansion */ - for (i = ofs + 1; i < calc_buffer_size; ++i) + for (i = nibble + 1; i < calc_buffer_size; ++i) calc_buffer[i] = SC_F; - calc_buffer[ofs] = or_table[(int) calc_buffer[ofs]][(int) sex_digit[bits & 3]]; + calc_buffer[nibble] = or_table[(int)calc_buffer[nibble]][(int)sex_digit[bits & 3]]; + } else { + /* set all bits to zero */ + for (i = nibble + 1; i < calc_buffer_size; ++i) + calc_buffer[i] = SC_0; + calc_buffer[nibble] = and_table[(int)calc_buffer[nibble]][(int)zex_digit[bits & 3]]; } + } else { + /* do zero extension */ + for (i = nibble + 1; i < calc_buffer_size; ++i) + calc_buffer[i] = SC_0; + calc_buffer[nibble] = and_table[(int)calc_buffer[nibble]][(int)zex_digit[bits & 3]]; } } diff --git a/ir/tv/tv.c b/ir/tv/tv.c index 63d8e7292..21dab027f 100644 --- a/ir/tv/tv.c +++ b/ir/tv/tv.c @@ -908,7 +908,10 @@ tarval *tarval_convert_to(tarval *src, ir_mode *m) switch (get_mode_sort(m)) { case irms_int_number: case irms_character: - return get_tarval_overflow(src->value, src->length, m); + buffer = alloca(sc_get_buffer_length()); + memcpy(buffer, src->value, sc_get_buffer_length()); + sign_extend(buffer, src->mode); + return get_tarval_overflow(buffer, src->length, m); case irms_internal_boolean: /* XXX C semantics */ -- 2.20.1