Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- This code is hereby released to the public domain.
- ~aaaaaa123456789, 2016-01-02
- */
- #include <stdlib.h>
- #include <string.h>
- #include <stdint.h>
- #define multibyte_is_zero(operand, size) ((int) ( \
- ((int) (size)) && \
- !(*((const unsigned char *) (operand))) && \
- !memcmp(operand, ((const unsigned char *) (operand)) + 1, ((int) (size)) - 1) \
- ))
- #define multibyte_is_negative(operand, size) (((int) (((const unsigned char *) (operand))[((int) (size)) - 1])) & 0x80)
- void multibyte_op (unsigned char * result, const unsigned char * operand0, const unsigned char * operand1, int op, unsigned size) {
- /*
- every two bits of op determine what to do with some intermediate result: 00 = nothing, 01 = subtract, 10 = add, 11 = add w/ negated shift
- bits 31-30: (operand0 AND operand1) >> shift amount, bits 29-28: (operand0 OR operand1) >> shift amount,
- bits 27-26: (operand0 AND operand1) << shift amount, bits 25-24: (operand0 OR operand1) << shift amount
- bits 23-0 of op indicate shift amount
- operand0 defaults to 0 if null, operand1 defaults to -1 if null
- EXAMPLE VALUES OF OP:
- 0x80000000 = AND, 0x20000000 = OR, 0x60000000 = XOR, 0xa0000000 = addition
- 0x60000000 with operand1 set to NULL = NOT, 0x10000000 with operand0 set to NULL = negate (-x)
- 0x2300xxxx = rotate right by xxxx, 0x3200xxxx = rotate left by xxxx, 0x2000xxxx = shift right by xxxx, 0x0200xxxx = shift left by xxxx
- (set operand0 to NULL for rotations and shifts)
- */
- if (!(size && result)) return;
- if (!(op & 0xff000000)) {
- memset(result, 0, size);
- return;
- }
- char * op0 = NULL;
- char * op1 = NULL;
- if (!operand0) operand0 = op0 = calloc(size, 1);
- if (!operand1) operand1 = op1 = memset(malloc(size), -1, size);
- unsigned char * temp_and = NULL;
- unsigned char * temp_or = NULL;
- if (op & 0xcc000000) temp_and = malloc(size);
- if (op & 0x33000000) temp_or = malloc(size);
- const unsigned char * p0 = operand0;
- const unsigned char * p1 = operand1;
- unsigned char * p2 = temp_and;
- unsigned char * p3 = temp_or;
- unsigned rem;
- for (rem = size; rem >= sizeof(uint_fast8_t); rem -= sizeof(uint_fast8_t)) {
- if (temp_and) {
- *((uint_fast8_t *) p2) = *((const uint_fast8_t *) p0) & *((const uint_fast8_t *) p1);
- p2 += sizeof(uint_fast8_t);
- }
- if (temp_or) {
- *((uint_fast8_t *) p3) = *((const uint_fast8_t *) p0) | *((const uint_fast8_t *) p1);
- p3 += sizeof(uint_fast8_t);
- }
- p0 += sizeof(uint_fast8_t);
- p1 += sizeof(uint_fast8_t);
- }
- for (; rem; rem --) {
- if (temp_and) *(p2 ++) = *p0 & *p1;
- if (temp_or) *(p3 ++) = *p0 | *p1;
- p0 ++;
- p1 ++;
- }
- free(op0);
- free(op1);
- int shift_amount = op & 0xffffff;
- if (shift_amount & 0x800000) shift_amount -= 0x1000000;
- shift_amount %= size << 3;
- if (shift_amount < 0) shift_amount += size << 3;
- unsigned char ** partials = calloc(sizeof(unsigned char *), 4);
- int inverted_shift_amount = (size << 3) - shift_amount;
- unsigned pending_shift_list = 0;
- int temp, pos;
- if (shift_amount) {
- if (op & 0xc0000000) {
- *partials = calloc(size, 1);
- temp = ((op & 0xc0000000) == 0xc0000000) ? inverted_shift_amount : shift_amount;
- memcpy(*partials, temp_and + (temp >> 3), size - (temp >> 3));
- pending_shift_list |= temp & 7;
- }
- if (op & 0x30000000) {
- partials[1] = calloc(size, 1);
- temp = ((op & 0x30000000) == 0x30000000) ? inverted_shift_amount : shift_amount;
- memcpy(partials[1], temp_or + (temp >> 3), size - (temp >> 3));
- pending_shift_list |= (temp & 7) << 3;
- }
- if (op & 0xc000000) {
- partials[2] = calloc(size, 1);
- temp = ((op & 0xc000000) == 0xc000000) ? inverted_shift_amount : shift_amount;
- memcpy(partials[2] + (temp >> 3), temp_and, size - (temp >> 3));
- pending_shift_list |= (temp & 7) << 6;
- }
- if (op & 0x3000000) {
- partials[3] = calloc(size, 1);
- temp = ((op & 0x3000000) == 0x3000000) ? inverted_shift_amount : shift_amount;
- memcpy(partials[3] + (temp >> 3), temp_or, size - (temp >> 3));
- pending_shift_list |= (temp & 7) << 9;
- }
- unsigned current_shift;
- for (current_shift = 0; current_shift < 4; pending_shift_list >>= 3, current_shift ++) {
- shift_amount = pending_shift_list & 7;
- if (!shift_amount) continue;
- temp = 0;
- if (current_shift & 2)
- for (pos = 0; pos < size; pos ++) {
- temp |= partials[current_shift][pos] << shift_amount;
- partials[current_shift][pos] = temp & 0xff;
- temp >>= 8;
- }
- else
- for (pos = size - 1; pos >= 0; pos --) {
- temp = (temp << 8) | partials[current_shift][pos];
- partials[current_shift][pos] = (temp >> shift_amount) & 0xff;
- }
- }
- } else {
- if (op & 0xc0000000) *partials = memcpy(malloc(size), temp_and, size);
- if (op & 0x30000000) partials[1] = memcpy(malloc(size), temp_or, size);
- if (op & 0x0c000000) partials[2] = memcpy(malloc(size), temp_and, size);
- if (op & 0x03000000) partials[3] = memcpy(malloc(size), temp_or, size);
- }
- free(temp_and);
- free(temp_or);
- temp = 0;
- int cp;
- for (pos = 0; pos < size; pos ++) {
- for (cp = 0; cp < 4; cp ++)
- if (op & (1 << (31 - (cp << 1))))
- temp += (int) partials[cp][pos];
- else if (op & (1 << (30 - (cp << 1))))
- temp -= (int) partials[cp][pos];
- result[pos] = temp & 0xff;
- temp >>= 8;
- }
- for (cp = 0; cp < 4; cp ++) free(partials[cp]);
- free(partials);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement