I ran into a rather peculiar problem. I am working on a compiler for an architecture that does not support bitwise operations. However, it handles the signed 16-bit integer arithmetic, and I was wondering if it is possible to implement bitwise operations using only:
- Addition (c = a + b)
- Subtraction (c = a - b)
- Department (c = a / b)
- Multiplication (c = a * b)
- Module (c = a% b)
- Minimum (c = min (a, b))
- Maximum (c = max (a, b))
- Comparison (c = (a <b), c = (a == b), c = (a <= b), et.c.)
- Transitions (goto, for, et.c.)
Bitwise operations that I want to support:
- Or (c = a | b)
- And (c = a and b)
- Xor (c = a ^ b)
- Left shift (c = a <b)
- Right shift (c = a β b)
- (All integers are signed, so this is a problem)
- Signed shift (c = a β> b)
- One addition (a = ~ b)
- (solution already found, see below)
Usually the problem is the opposite; how to achieve arithmetic optimization using bitwise hacks. However, not in this case.
Writable memory is very scarce in this architecture, therefore, bitwise operation is required. Bitwise functions themselves should not use many temporary variables. However, read-only persistent data and memory commands are plentiful. Also note that jumps and branches are not expensive, and all data is easily cached. Jumps cost half a cycle, as arithmetic instructions do (including loading / storing). In other words, all of the above supported functions cost twice as many cycles of one jump.
Some thoughts that may help:
I realized that you can make one addition (negation of bits) with the following code:
I also remember the old cracked shift when dividing with a power of two, so the bitwise shift can be expressed as:
For the remaining bitwise operations, I do not know a bit. I want the architects of this architecture to provide bit operations.
I would also like to know if there is a quick / easy way to calculate the power of two (for shift operations) without using a memory data table. A naive solution would be to go to the multiplication field:
b = 1; switch (a) { case 15: b = b * 2; case 14: b = b * 2; // ... exploting fallthrough (instruction memory is magnitudes larger) case 2: b = b * 2; case 1: b = b * 2; }
Or the Set and Jump approach:
switch (a) { case 15: b = 32768; break; case 14: b = 16384; break;
compiler-optimization bitwise-operators discrete-mathematics
Statement Jun 06 2018-10-06T00: 00Z
source share