Advertisement
aaaaaa123456789

Multibyte bitwise operations

Jan 2nd, 2016
115
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.    This code is hereby released to the public domain.
  3.    ~aaaaaa123456789, 2016-01-02
  4. */
  5.  
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <stdint.h>
  9.  
  10. #define multibyte_is_zero(operand, size) ((int) (                                                                           \
  11.                                            ((int) (size)) &&                                                                \
  12.                                            !(*((const unsigned char *) (operand))) &&                                       \
  13.                                            !memcmp(operand, ((const unsigned char *) (operand)) + 1, ((int) (size)) - 1)    \
  14.                                          ))
  15.  
  16. #define multibyte_is_negative(operand, size) (((int) (((const unsigned char *) (operand))[((int) (size)) - 1])) & 0x80)
  17.  
  18. void multibyte_op (unsigned char * result, const unsigned char * operand0, const unsigned char * operand1, int op, unsigned size) {
  19.   /*
  20.     every two bits of op determine what to do with some intermediate result: 00 = nothing, 01 = subtract, 10 = add, 11 = add w/ negated shift
  21.     bits 31-30: (operand0 AND operand1) >> shift amount, bits 29-28: (operand0 OR operand1) >> shift amount,
  22.     bits 27-26: (operand0 AND operand1) << shift amount, bits 25-24: (operand0 OR operand1) << shift amount
  23.     bits 23-0 of op indicate shift amount
  24.     operand0 defaults to 0 if null, operand1 defaults to -1 if null
  25.    
  26.     EXAMPLE VALUES OF OP:
  27.     0x80000000 = AND, 0x20000000 = OR, 0x60000000 = XOR, 0xa0000000 = addition
  28.     0x60000000 with operand1 set to NULL = NOT, 0x10000000 with operand0 set to NULL = negate (-x)
  29.     0x2300xxxx = rotate right by xxxx, 0x3200xxxx = rotate left by xxxx, 0x2000xxxx = shift right by xxxx, 0x0200xxxx = shift left by xxxx
  30.     (set operand0 to NULL for rotations and shifts)
  31.   */
  32.   if (!(size && result)) return;
  33.   if (!(op & 0xff000000)) {
  34.     memset(result, 0, size);
  35.     return;
  36.   }
  37.   char * op0 = NULL;
  38.   char * op1 = NULL;
  39.   if (!operand0) operand0 = op0 = calloc(size, 1);
  40.   if (!operand1) operand1 = op1 = memset(malloc(size), -1, size);
  41.   unsigned char * temp_and = NULL;
  42.   unsigned char * temp_or = NULL;
  43.   if (op & 0xcc000000) temp_and = malloc(size);
  44.   if (op & 0x33000000) temp_or = malloc(size);
  45.   const unsigned char * p0 = operand0;
  46.   const unsigned char * p1 = operand1;
  47.   unsigned char * p2 = temp_and;
  48.   unsigned char * p3 = temp_or;
  49.   unsigned rem;
  50.   for (rem = size; rem >= sizeof(uint_fast8_t); rem -= sizeof(uint_fast8_t)) {
  51.     if (temp_and) {
  52.       *((uint_fast8_t *) p2) = *((const uint_fast8_t *) p0) & *((const uint_fast8_t *) p1);
  53.       p2 += sizeof(uint_fast8_t);
  54.     }
  55.     if (temp_or) {
  56.       *((uint_fast8_t *) p3) = *((const uint_fast8_t *) p0) | *((const uint_fast8_t *) p1);
  57.       p3 += sizeof(uint_fast8_t);
  58.     }
  59.     p0 += sizeof(uint_fast8_t);
  60.     p1 += sizeof(uint_fast8_t);
  61.   }
  62.   for (; rem; rem --) {
  63.     if (temp_and) *(p2 ++) = *p0 & *p1;
  64.     if (temp_or) *(p3 ++) = *p0 | *p1;
  65.     p0 ++;
  66.     p1 ++;
  67.   }
  68.   free(op0);
  69.   free(op1);
  70.   int shift_amount = op & 0xffffff;
  71.   if (shift_amount & 0x800000) shift_amount -= 0x1000000;
  72.   shift_amount %= size << 3;
  73.   if (shift_amount < 0) shift_amount += size << 3;
  74.   unsigned char ** partials = calloc(sizeof(unsigned char *), 4);
  75.   int inverted_shift_amount = (size << 3) - shift_amount;
  76.   unsigned pending_shift_list = 0;
  77.   int temp, pos;
  78.   if (shift_amount) {
  79.     if (op & 0xc0000000) {
  80.       *partials = calloc(size, 1);
  81.       temp = ((op & 0xc0000000) == 0xc0000000) ? inverted_shift_amount : shift_amount;
  82.       memcpy(*partials, temp_and + (temp >> 3), size - (temp >> 3));
  83.       pending_shift_list |= temp & 7;
  84.     }
  85.     if (op & 0x30000000) {
  86.       partials[1] = calloc(size, 1);
  87.       temp = ((op & 0x30000000) == 0x30000000) ? inverted_shift_amount : shift_amount;
  88.       memcpy(partials[1], temp_or + (temp >> 3), size - (temp >> 3));
  89.       pending_shift_list |= (temp & 7) << 3;
  90.     }
  91.     if (op & 0xc000000) {
  92.       partials[2] = calloc(size, 1);
  93.       temp = ((op & 0xc000000) == 0xc000000) ? inverted_shift_amount : shift_amount;
  94.       memcpy(partials[2] + (temp >> 3), temp_and, size - (temp >> 3));
  95.       pending_shift_list |= (temp & 7) << 6;
  96.     }
  97.     if (op & 0x3000000) {
  98.       partials[3] = calloc(size, 1);
  99.       temp = ((op & 0x3000000) == 0x3000000) ? inverted_shift_amount : shift_amount;
  100.       memcpy(partials[3] + (temp >> 3), temp_or, size - (temp >> 3));
  101.       pending_shift_list |= (temp & 7) << 9;
  102.     }
  103.     unsigned current_shift;
  104.     for (current_shift = 0; current_shift < 4; pending_shift_list >>= 3, current_shift ++) {
  105.       shift_amount = pending_shift_list & 7;
  106.       if (!shift_amount) continue;
  107.       temp = 0;
  108.       if (current_shift & 2)
  109.         for (pos = 0; pos < size; pos ++) {
  110.           temp |= partials[current_shift][pos] << shift_amount;
  111.           partials[current_shift][pos] = temp & 0xff;
  112.           temp >>= 8;
  113.         }
  114.       else
  115.         for (pos = size - 1; pos >= 0; pos --) {
  116.           temp = (temp << 8) | partials[current_shift][pos];
  117.           partials[current_shift][pos] = (temp >> shift_amount) & 0xff;
  118.         }
  119.     }
  120.   } else {
  121.     if (op & 0xc0000000) *partials = memcpy(malloc(size), temp_and, size);
  122.     if (op & 0x30000000) partials[1] = memcpy(malloc(size), temp_or, size);
  123.     if (op & 0x0c000000) partials[2] = memcpy(malloc(size), temp_and, size);
  124.     if (op & 0x03000000) partials[3] = memcpy(malloc(size), temp_or, size);
  125.   }
  126.   free(temp_and);
  127.   free(temp_or);
  128.   temp = 0;
  129.   int cp;
  130.   for (pos = 0; pos < size; pos ++) {
  131.     for (cp = 0; cp < 4; cp ++)
  132.       if (op & (1 << (31 - (cp << 1))))
  133.         temp += (int) partials[cp][pos];
  134.       else if (op & (1 << (30 - (cp << 1))))
  135.         temp -= (int) partials[cp][pos];
  136.     result[pos] = temp & 0xff;
  137.     temp >>= 8;
  138.   }
  139.   for (cp = 0; cp < 4; cp ++) free(partials[cp]);
  140.   free(partials);
  141. }
Advertisement
RAW Paste Data Copied
Advertisement