+ *pos++ = max_digit[bits%4];
+
+ for (i++; i <= calc_buffer_size - 1; i++)
+ *pos++ = SC_0;
+}
+
+void sc_calc(const void* value1, const void* value2, unsigned op, void *buffer) {
+ char *unused_res; /* temp buffer holding unused result of divmod */
+
+ const char *val1 = (const char *)value1;
+ const char *val2 = (const char *)value2;
+
+ unused_res = alloca(calc_buffer_size);
+
+ CLEAR_BUFFER(calc_buffer);
+ carry_flag = 0;
+
+ DEBUGPRINTF_COMPUTATION(("%s ", sc_print_hex(value1)));
+
+ switch (op) {
+ case SC_NEG:
+ _negate(val1, calc_buffer);
+ DEBUGPRINTF_COMPUTATION(("negated: %s\n", sc_print_hex(calc_buffer)));
+ break;
+ case SC_OR:
+ DEBUGPRINTF_COMPUTATION(("| "));
+ _bitor(val1, val2, calc_buffer);
+ break;
+ case SC_AND:
+ DEBUGPRINTF_COMPUTATION(("& "));
+ _bitand(val1, val2, calc_buffer);
+ break;
+ case SC_XOR:
+ DEBUGPRINTF_COMPUTATION(("^ "));
+ _bitxor(val1, val2, calc_buffer);
+ break;
+ case SC_NOT:
+ _bitnot(val1, calc_buffer);
+ DEBUGPRINTF_COMPUTATION(("bit-negated: %s\n", sc_print_hex(calc_buffer)));
+ break;
+ case SC_ADD:
+ DEBUGPRINTF_COMPUTATION(("+ "));
+ _add(val1, val2, calc_buffer);
+ break;
+ case SC_SUB:
+ DEBUGPRINTF_COMPUTATION(("- "));
+ _sub(val1, val2, calc_buffer);
+ break;
+ case SC_MUL:
+ DEBUGPRINTF_COMPUTATION(("* "));
+ _mul(val1, val2, calc_buffer);
+ break;
+ case SC_DIV:
+ DEBUGPRINTF_COMPUTATION(("/ "));
+ _divmod(val1, val2, calc_buffer, unused_res);
+ break;
+ case SC_MOD:
+ DEBUGPRINTF_COMPUTATION(("%% "));
+ _divmod(val1, val2, unused_res, calc_buffer);
+ break;
+ default:
+ assert(0);
+ }
+ DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
+ DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
+
+ if ((buffer != NULL) && (buffer != calc_buffer)) {
+ memcpy(buffer, calc_buffer, calc_buffer_size);
+ }
+}
+
+void sc_bitcalc(const void* value1, const void* value2, int radius, int sign, unsigned op, void* buffer) {
+ const char *val1 = (const char *)value1;
+ const char *val2 = (const char *)value2;
+ long offset;
+
+ carry_flag = 0;
+ offset = sc_val_to_long(val2);
+
+ DEBUGPRINTF_COMPUTATION(("%s ", sc_print_hex(value1)));
+ switch (op) {
+ case SC_SHL:
+ DEBUGPRINTF_COMPUTATION(("<< %ld ", offset));
+ _shl(val1, calc_buffer, offset, radius, sign);
+ break;
+ case SC_SHR:
+ DEBUGPRINTF_COMPUTATION((">> %ld ", offset));
+ _shr(val1, calc_buffer, offset, radius, sign, 0);
+ break;
+ case SC_SHRS:
+ DEBUGPRINTF_COMPUTATION((">>> %ld ", offset));
+ _shr(val1, calc_buffer, offset, radius, sign, 1);
+ break;
+ case SC_ROT:
+ DEBUGPRINTF_COMPUTATION(("<<>> %ld ", offset));
+ _rot(val1, calc_buffer, offset, radius, sign);
+ break;
+ default:
+ assert(0);
+ }
+ DEBUGPRINTF_COMPUTATION(("-> %s\n", sc_print_hex(calc_buffer)));
+
+ if ((buffer != NULL) && (buffer != calc_buffer)) {
+ memmove(buffer, calc_buffer, calc_buffer_size);
+ }
+}