#include <limits.h> /* definition of LONG_MIN, used in sc_get_val_from_long */
#include "strcalc.h"
+#include "xmalloc.h"
/*
* local definitions and macros
#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
However, the meaning of carry is machine dependent
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"));
return (void*)calc_buffer;
}
-const int sc_get_buffer_length(void)
+int sc_get_buffer_length(void)
{
return calc_buffer_size;
}
+/**
+ * Do sign extension if the mode is signed, otherwise to zero extension.
+ */
+void sign_extend(char *calc_buffer, ir_mode *mode) {
+ int bits = get_mode_size_bits(mode) - 1;
+ int nibble = bits >> 2;
+ int max = max_digit[bits & 3];
+ int i;
+
+ if (mode_is_signed(mode)) {
+ if (calc_buffer[nibble] > max) {
+ /* sign bit is set, we need sign expansion */
+
+ for (i = nibble + 1; i < calc_buffer_size; ++i)
+ calc_buffer[i] = SC_F;
+ 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]];
+ }
+}
+
/* FIXME doesn't check for overflows */
-void sc_val_from_str(const char *str, unsigned int len, void *buffer)
+void sc_val_from_str(const char *str, unsigned int len, void *buffer, ir_mode *mode)
{
const char *orig_str = str;
unsigned int orig_len = len;
if (buffer == NULL) buffer = calc_buffer;
CLEAR_BUFFER(buffer);
- memset(base, SC_0, calc_buffer_size);
- memset(val, SC_0, calc_buffer_size);
+ CLEAR_BUFFER(base);
+ CLEAR_BUFFER(val);
/* strip leading spaces */
while ((len > 0) && (*str == ' ')) { len--; str++; }
} /* while (len > 0 ) */
if (sign)
- {
_negate(calc_buffer, calc_buffer);
- }
+
+ /* beware: even if hex numbers have no sign, we need sign extension here */
+ sign_extend(calc_buffer, mode);
}
void sc_val_from_long(long value, void *buffer)
sign = (value < 0);
is_minlong = value == LONG_MIN;
- /* use absolute value, special treatment of MIN_LONG */
+ /* use absolute value, special treatment of MIN_LONG to avoid overflow */
if (sign) {
if (is_minlong)
value = -(value+1);
value >>= 4;
}
-
if (sign) {
if (is_minlong)
_inc(buffer, buffer);
if (buffer == NULL) buffer = calc_buffer;
pos = buffer;
- while (pos < (char*)buffer + calc_buffer_size)
+ while (pos < (unsigned char *)buffer + calc_buffer_size)
{
*pos++ = (unsigned char)_digit(value & 0xf);
value >>= 4;
* 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)
calc_buffer_size = (precision / 2);
max_value_size = (precision / 4);
- calc_buffer = malloc(calc_buffer_size+1 * sizeof(char));
- output_buffer = malloc(bit_pattern_size+1 * sizeof(char));
-
- if (calc_buffer == NULL || output_buffer == NULL) {
- assert(0 && "malloc failed");
- exit(-1);
- }
+ calc_buffer = xmalloc(calc_buffer_size+1 * sizeof(char));
+ output_buffer = xmalloc(bit_pattern_size+1 * sizeof(char));
DEBUGPRINTF(("init strcalc: \n\tPRECISION: %d\n\tCALC_BUFFER_SIZE = %d\n\tMAX_VALUE_SIZE = %d\n\tbuffer pointer: %p\n", precision, calc_buffer_size, max_value_size, calc_buffer));
}