AaronMiller
-
C,
pasted
on Feb 23:
|
/*
When selecting between two values without branching (e.g., in a virtual machine),
you can use a specific bit (or bit pattern) to select between the two values, like
so:
int a, b; -- a = value 0, b = value 1
int instr; -- the instruction
int v; -- v is the resulting value
v = (a&(-((instr & (1<<bit_id))>>bit_id))) | (b&(-((~instr & (1<<bit_id))>>bit_id)));
--------------------------------------------------------
a = 1101
b = 0110
instr = 0100
instr & (1<<2) = 0100 & 4 = 0100 & 0100 = 0100
0100 >> 2 = 0001
-0001 = 1111
~instr & (1<<2) = 1011 & 4 = 1011 & 0100 = 0000
0000 >> 2 = 0000
-0000 = 0000
a&1111 | b&0000 = 1101&1111 | 0110&0000 = 1101 | 0000 = 1101
*/
int selectfrombit(int instr, int bit_id, int a, int b) {
return (a&(-((instr & (1<<bit_id))>>bit_id))) | (b&(-((~instr & (1<<bit_id))>>bit_id)));
}
void selectfrombit_test(int instr, int bit_id, int a, int b) {
printf("selectfrombit(%i, %i, %i, %i) = %i\n", instr, bit_id, a, b, selectfrombit(instr, bit_id, a, b));
}
int main() {
selectfrombit_test(4, 2, 42, 23);
selectfrombit_test(8, 2, 42, 23);
selectfrombit_test(2, 2, 20, 30);
selectfrombit_test(2, 1, 20, 30);
selectfrombit_test(2, 0, 20, 30);
return 0;
}
|
Output:
|
selectfrombit(4, 2, 42, 23) = 42
selectfrombit(8, 2, 42, 23) = 23
selectfrombit(2, 2, 20, 30) = 30
selectfrombit(2, 1, 20, 30) = 20
selectfrombit(2, 0, 20, 30) = 30
|
|