- if (pos[0] != '0')
- break;
- }
- break;
-
- case SC_BIN:
- for (counter = 0; counter < nibbles; ++counter) {
- pos -= 4;
- p = binary_table[_val(val[counter])];
- pos[0] = p[0];
- pos[1] = p[1];
- pos[2] = p[2];
- pos[3] = p[3];
- }
-
- /* last nibble must be masked */
- if (bits & 3) {
- x = and_table[_val(val[++counter])][bits & 3];
-
- pos -= 4;
- p = binary_table[_val(x)];
- pos[0] = p[0];
- pos[1] = p[1];
- pos[2] = p[2];
- pos[3] = p[3];
- }
-
- /* now kill zeros */
- for (counter <<= 2; counter > 1; --counter, ++pos)
- if (pos[0] != '0')
- break;
- break;
-
- case SC_DEC:
- case SC_OCT:
- memset(base_val, SC_0, calc_buffer_size);
- base_val[0] = base == SC_DEC ? SC_A : SC_8;
-
- p = val;
- sign = 0;
- if (signed_mode && base == SC_DEC) {
- /* check for negative values */
- if (_bit(val, bits - 1)) {
- _negate(val, div2_res);
- sign = 1;
- p = div2_res;
- }
- }
-
- /* transfer data into oscillating buffers */
- memset(div1_res, SC_0, calc_buffer_size);
- for (counter = 0; counter < nibbles; ++counter)
- div1_res[counter] = p[counter];
-
- /* last nibble must be masked */
- if (bits & 3) {
- ++counter;
-
- div1_res[counter] = and_table[_val(p[counter])][bits & 3];
- }
-
- m = div1_res;
- n = div2_res;
- for (;;) {
- _divmod(m, base_val, n, rem_res);
- t = m;
- m = n;
- n = t;
- *(--pos) = digits[_val(rem_res[0])];
-
- x = 0;
- for (i = 0; i < calc_buffer_size; ++i)
- x |= _val(m[i]);
-
- if (x == 0)
- break;
- }
- if (sign)
- *(--pos) = '-';
- break;
-
- default:
- printf("%i\n", base);
- assert(0);
- return NULL;
+ if (pos[0] != '0')
+ break;
+ }
+ break;
+
+ case SC_BIN:
+ for (counter = 0; counter < nibbles; ++counter) {
+ pos -= 4;
+ p = binary_table[_val(val[counter])];
+ pos[0] = p[0];
+ pos[1] = p[1];
+ pos[2] = p[2];
+ pos[3] = p[3];
+ }
+
+ /* last nibble must be masked */
+ if (bits & 3) {
+ mask = zex_digit[bits & 3];
+ x = and_table[_val(val[counter++])][mask];
+
+ pos -= 4;
+ p = binary_table[_val(x)];
+ pos[0] = p[0];
+ pos[1] = p[1];
+ pos[2] = p[2];
+ pos[3] = p[3];
+ }
+
+ /* now kill zeros */
+ for (counter <<= 2; counter > 1; --counter, ++pos)
+ if (pos[0] != '0')
+ break;
+ break;
+
+ case SC_DEC:
+ case SC_OCT:
+ memset(base_val, SC_0, calc_buffer_size);
+ base_val[0] = base == SC_DEC ? SC_A : SC_8;
+
+ p = val;
+ sign = 0;
+ if (signed_mode && base == SC_DEC) {
+ /* check for negative values */
+ if (do_bit(val, bits - 1)) {
+ do_negate(val, div2_res);
+ sign = 1;
+ p = div2_res;
+ }
+ }
+
+ /* transfer data into oscillating buffers */
+ memset(div1_res, SC_0, calc_buffer_size);
+ for (counter = 0; counter < nibbles; ++counter)
+ div1_res[counter] = p[counter];
+
+ /* last nibble must be masked */
+ if (bits & 3) {
+ mask = zex_digit[bits & 3];
+ div1_res[counter] = and_table[_val(p[counter])][mask];
+ ++counter;
+ }
+
+ m = div1_res;
+ n = div2_res;
+ for (;;) {
+ do_divmod(m, base_val, n, rem_res);
+ t = m;
+ m = n;
+ n = t;
+ *(--pos) = digits[_val(rem_res[0])];
+
+ x = 0;
+ for (i = 0; i < calc_buffer_size; ++i)
+ x |= _val(m[i]);
+
+ if (x == 0)
+ break;
+ }
+ if (sign)
+ *(--pos) = '-';
+ break;
+
+ default:
+ panic("Unsupported base %d", base);
+ }
+ return pos;
+}
+
+void init_strcalc(int precision) {
+ if (calc_buffer == NULL) {
+ if (precision <= 0) precision = SC_DEFAULT_PRECISION;
+
+ /* round up to multiple of 4 */
+ precision = (precision + 3) & ~3;
+
+ bit_pattern_size = (precision);
+ calc_buffer_size = (precision / 2);
+ max_value_size = (precision / 4);
+
+ calc_buffer = XMALLOCN(char, calc_buffer_size + 1);
+ output_buffer = XMALLOCN(char, bit_pattern_size + 1);
+
+ 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));
+ }
+}
+
+
+void finish_strcalc(void) {
+ free(calc_buffer); calc_buffer = NULL;
+ free(output_buffer); output_buffer = NULL;
+}
+
+int sc_get_precision(void) {
+ return bit_pattern_size;
+}
+
+
+void sc_add(const void *value1, const void *value2, void *buffer) {
+ CLEAR_BUFFER(calc_buffer);
+ carry_flag = 0;
+
+ DEBUGPRINTF_COMPUTATION(("%s + ", sc_print_hex(value1)));
+ DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
+
+ do_add(value1, value2, calc_buffer);
+
+ DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
+
+ if ((buffer != NULL) && (buffer != calc_buffer)) {
+ memcpy(buffer, calc_buffer, calc_buffer_size);
+ }
+}
+
+void sc_sub(const void *value1, const void *value2, void *buffer) {
+ CLEAR_BUFFER(calc_buffer);
+ carry_flag = 0;
+
+ DEBUGPRINTF_COMPUTATION(("%s - ", sc_print_hex(value1)));
+ DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
+
+ do_sub(value1, value2, calc_buffer);
+
+ DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
+
+ if ((buffer != NULL) && (buffer != calc_buffer)) {
+ memcpy(buffer, calc_buffer, calc_buffer_size);
+ }
+}
+
+void sc_neg(const void *value1, void *buffer) {
+ carry_flag = 0;
+
+ DEBUGPRINTF_COMPUTATION(("- %s ->", sc_print_hex(value1)));
+
+ do_negate(value1, calc_buffer);
+
+ DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
+
+ if ((buffer != NULL) && (buffer != calc_buffer)) {
+ memcpy(buffer, calc_buffer, calc_buffer_size);
+ }
+}
+
+void sc_and(const void *value1, const void *value2, void *buffer) {
+ CLEAR_BUFFER(calc_buffer);
+ carry_flag = 0;
+
+ DEBUGPRINTF_COMPUTATION(("%s & ", sc_print_hex(value1)));
+ DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
+
+ do_bitand(value1, value2, calc_buffer);
+
+ DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
+
+ if ((buffer != NULL) && (buffer != calc_buffer)) {
+ memcpy(buffer, calc_buffer, calc_buffer_size);
+ }
+}
+
+void sc_or(const void *value1, const void *value2, void *buffer) {
+ CLEAR_BUFFER(calc_buffer);
+ carry_flag = 0;
+
+ DEBUGPRINTF_COMPUTATION(("%s | ", sc_print_hex(value1)));
+ DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
+
+ do_bitor(value1, value2, calc_buffer);
+
+ DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
+
+ if ((buffer != NULL) && (buffer != calc_buffer)) {
+ memcpy(buffer, calc_buffer, calc_buffer_size);
+ }