-/* FIXME doesn't check for overflows */
-void sc_val_from_str(const char *str, unsigned int len, void *buffer)
-{
- const char *orig_str = str;
- unsigned int orig_len = len;
-
- char sign = 0;
- char *base, *val;
-
- base = alloca(calc_buffer_size);
- val = alloca(calc_buffer_size);
-
- /* verify valid pointers (not null) */
- assert(str);
- /* a string no characters long is an error */
- assert(len);
-
- if (buffer == NULL) buffer = calc_buffer;
-
- CLEAR_BUFFER(buffer);
- memset(base, SC_0, calc_buffer_size);
- memset(val, SC_0, calc_buffer_size);
-
- /* strip leading spaces */
- while ((len > 0) && (*str == ' ')) { len--; str++; }
-
- /* if the first two characters are 0x or 0X -> hex
- * if the first is a 0 -> oct
- * else dec, strip leading -/+ and remember sign
- *
- * only a + or - sign is no number resulting in an error */
- if (len >= 2)
- switch (str[0])
- {
- case '0':
- if (str[1] == 'x' || str[1] == 'X') /* hex */
- {
- str += 2;
- len -= 2;
- base[1] = SC_1; base[0] = SC_0;
- }
- else /* oct */
- {
- str += 1;
- len -= 1;
- base[1] = SC_0; base[0] = SC_8;
- }
- break;
-
- case '+':
- {
- str += 1;
- len -= 1;
- base[1] = SC_0; base[0] = SC_A;
- }
- break;
-
- case '-':
- {
- str += 1;
- len -= 1;
- sign = 1;
- base[1] = SC_0; base[0] = SC_A;
- }
- break;
-
- default: /* dec, else would have begun with 0x or 0 */
- base[1] = SC_0; base[0] = SC_A;
- }
-
- else /* dec, else would have begun with 0x or 0 */
- {
- base[1] = SC_0; base[0] = SC_A;
- }
-
- /* BEGIN string evaluation, from left to right */
- while (len > 0)
- {
- switch (*str)
- {
- case 'f':
- case 'e':
- case 'd':
- case 'c':
- case 'b':
- case 'a':
- if (base[0] > SC_9 || base[1] > SC_0) /* (base > 10) */
- {
- val[0] = _digit((*str)-'a'+10);
- }
- else fail_char(orig_str, orig_len, *str, str-orig_str+1);
- break;
-
- case 'F':
- case 'E':
- case 'D':
- case 'C':
- case 'B':
- case 'A':
- if (base[0] > SC_9 || base[1] > SC_0) /* (base > 10) */
- {
- val[0] = _digit((*str)-'A'+10);
- }
- else fail_char(orig_str, orig_len, *str, str-orig_str+1);
- break;
-
- case '9':
- case '8':
- if (base[0] > SC_7 || base[1] > SC_0) /* (base > 8) */
- {
- val[0] = _digit((*str)-'0');
- }
- else fail_char(orig_str, orig_len, *str, str-orig_str+1);
- break;
-
- case '7':
- case '6':
- case '5':
- case '4':
- case '3':
- case '2':
- case '1':
- case '0':
- {
- val[0] = _digit((*str)-'0');
- }
- break;
-
- default:
- fail_char(orig_str, orig_len, *str, str-orig_str+1);
- } /* switch(*str) */
-
- /* Radix conversion from base b to base B:
- * (UnUn-1...U1U0)b == ((((Un*b + Un-1)*b + ...)*b + U1)*b + U0)B */
- _mul(base, calc_buffer, calc_buffer); /* multiply current value with base */
- _add(val, calc_buffer, calc_buffer); /* add next digit to current value */
-
- /* get ready for the next letter */
- str++;
- len--;
-
- } /* while (len > 0 ) */
-
- if (sign)
- {
- _negate(calc_buffer, calc_buffer);
- }
+/**
+ * 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]];
+ }