/*
- * Project: libFIRM
- * File name: ir/tv/strcalc.c
- * Purpose:
- * Author: Mathias Heil
- * Modified by:
- * Created:
- * CVS-ID: $Id$
- * Copyright: (c) 2003 Universität Karlsruhe
- * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
+ * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
+ *
+ * This file is part of libFirm.
+ *
+ * This file may be distributed and/or modified under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * Licensees holding valid libFirm Professional Edition licenses may use
+ * this file in accordance with the libFirm Commercial License.
+ * Agreement provided with the Software.
+ *
+ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE.
*/
+/**
+ * @file
+ * @brief Provides basic mathematical operations on values represented as strings.
+ * @date 2003
+ * @author Mathias Heil
+ * @version $Id$
+ */
#ifdef HAVE_CONFIG_H
# include "config.h"
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
-#ifdef HAVE_ALLOCA_H
-# include <alloca.h>
-#endif
-#ifdef HAVE_MALLOC_H
-# include <malloc.h>
-#endif
#ifdef HAVE_STRING_H
# include <string.h> /* memset/memcmp */
#endif
#define fail_char(a, b, c, d) _fail_char((a), (b), (c), (d), __FILE__, __LINE__)
/* shortcut output for debugging */
-# 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)
+# define sc_print_hex(a) sc_print((a), 0, SC_HEX, 0)
+# define sc_print_dec(a) sc_print((a), 0, SC_DEC, 1)
+# define sc_print_oct(a) sc_print((a), 0, SC_OCT, 0)
+# define sc_print_bin(a) sc_print((a), 0, SC_BIN, 0)
#ifdef STRCALC_DEBUG_PRINTCOMP
# define DEBUGPRINTF_COMPUTATION(x) printf x
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 };
int bitoffset = 0;
assert((offset >= 0) || (0 && "negative rightshift"));
- 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"));
}
/**
- * 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[calc_buffer[ofs]][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]];
}
}
* convert to a string
* FIXME: Doesn't check buffer bounds
*/
-const char *sc_print(const void *value, unsigned bits, enum base_t base)
+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";
base_val = alloca(calc_buffer_size);
div1_res = alloca(calc_buffer_size);
div2_res = alloca(calc_buffer_size);
- rem_res = alloca(calc_buffer_size);
+ rem_res = alloca(calc_buffer_size);
pos = output_buffer + bit_pattern_size;
*(--pos) = '\0';
p = val;
sign = 0;
- if (base == SC_DEC) {
+ if (signed_mode && base == SC_DEC) {
/* check for negative values */
if (_bit(val, bits - 1)) {
_negate(val, div2_res);
*(--pos) = digits[_val(rem_res[0])];
x = 0;
- for (i = 0; i < sizeof(div1_res); ++i)
+ for (i = 0; i < calc_buffer_size; ++i)
x |= _val(m[i]);
if (x == 0)