#include #include #include #define Ch(x, y, z) ((x & y) ^ (~x & z)) #define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) #define f(x, y, z) ((y) ^ ((x) | ~(z))) //#define f(x, y, z) ((x & y) | (z & (x | y))) //#define f(x, y, z) Ch(x, y, z) //#define f(x, y, z) Maj(x, y, z) #define sel(x, y, z) ((x) ^ ((z) & ((y) ^ (x)))) static int no_sel, no_xnor, no_orn, no_andn; static char how[0x100]; static void reorder(unsigned int a[3], unsigned int r) { unsigned int x = a[0], y = a[1], z = a[2]; switch (r) { case 1: a[0] = x; a[1] = z; a[2] = y; break; case 2: a[0] = y; a[1] = x; a[2] = z; break; case 3: a[0] = y; a[1] = z; a[2] = x; break; case 4: a[0] = z; a[1] = x; a[2] = y; break; case 5: a[0] = z; a[1] = y; a[2] = x; break; } } static unsigned int save_op(unsigned int x, unsigned int y, unsigned int r, char *op) { sprintf(how + strlen(how), " %02x %s %02x = %02x;", x & 0xff, op, y & 0xff, r & 0xff); return r; } static unsigned int save_sel(unsigned int x, unsigned int y, unsigned int z) { unsigned int r = sel(x, y, z); sprintf(how + strlen(how), " sel(%02x, %02x, %02x) = %02x;", x & 0xff, y & 0xff, z & 0xff, r & 0xff); return r; } static unsigned int op(unsigned int x, unsigned int y, unsigned int z, unsigned int o) { switch (o) { case 0: if (no_sel) return 0xdead; return save_sel(x, y, z); case 1: return 0; case 2: return 0xff; case 3: return x; case 4: return ~x; case 5: return save_op(x, y, x ^ y, "^"); case 6: return save_op(x, y, x | y, "|"); case 7: return save_op(x, y, x & y, "&"); case 8: if (no_xnor) return 0xdead; return save_op(x, y, x ^ ~y, "^~"); case 9: if (no_orn) return 0xdead; return save_op(x, y, x | ~y, "|~"); case 10: if (no_andn) return 0xdead; return save_op(x, y, x & ~y, "&~"); } abort(); } int main(int argc, char **argv) { unsigned int i, j, k, m, n, o; unsigned int diff = 0; char seen[0x100] = {0}; if (argc == 5) { no_sel = argv[1][0] == 'n'; no_xnor = argv[2][0] == 'n'; no_orn = argv[3][0] == 'n'; no_andn = argv[4][0] == 'n'; } for (o = 0; o <= 10; o++) for (n = 0; n <= 8; n++) #ifdef DUPES for (m = 0; m <= 12; m++) #else for (m = 0; m <= 6; m++) #endif for (k = 0; k <= 75; k++) for (j = 0; j < 6; j++) for (i = 0; i < 4; i++) { unsigned int x = 0x55, y = 0x33, z = 0x0f; unsigned int a[4] = {0xdead, x, y, z}; how[0] = 0; reorder(&a[1], j); #ifdef DUPES if (m >= 7 && m <= 9) a[m - 6] = 0; else if (m >= 10) a[m - 9] = 0xff; #endif if (!i) { a[0] = op(a[1], a[2], a[3], o); if (a[0] == 0xdead) continue; } #ifndef DUPES if ((k != 25 && k != 26) || (i != m && i != m - 3)) { #endif if (m >= 1 && m <= 3) a[m] = 0; else if (m >= 4 && m <= 6) a[m - 3] = 0xff; #ifndef DUPES } #endif #ifdef DUPES #define maybe_continue #else #define maybe_continue continue #endif if (k == 27 && i) maybe_continue; unsigned int *which = &a[i]; switch (k) { case 0: *which = op(*which, 0, 0, 4); break; case 1: case 2: case 3: if (which == &a[k]) maybe_continue; *which = op(*which, a[k], 0, 5); break; case 4: case 5: case 6: if (which == &a[k - 3]) maybe_continue; *which = op(*which, a[k - 3], 0, 6); break; case 7: case 8: case 9: if (which == &a[k - 6]) maybe_continue; *which = op(*which, a[k - 6], 0, 7); break; case 10: case 11: case 12: if (no_xnor) continue; if (which == &a[k - 9]) maybe_continue; *which = op(*which, a[k - 9], 0, 8); break; case 13: case 14: case 15: if (no_orn) continue; if (which == &a[k - 12]) maybe_continue; *which = op(*which, a[k - 12], 0, 9); break; #ifdef DUPES case 16: case 17: case 18: if (no_orn) continue; if (which == &a[k - 15]) maybe_continue; *which = op(*which, a[k - 15], 0, 9); break; #endif case 19: case 20: case 21: if (no_andn) continue; if (which == &a[k - 18]) maybe_continue; *which = op(*which, a[k - 18], 0, 10); break; #ifdef DUPES case 22: case 23: case 24: if (no_andn) continue; if (which == &a[k - 21]) maybe_continue; *which = op(*which, a[k - 21], 0, 11); break; case 25: maybe_continue; if (which == &a[0]) maybe_continue; *which = 0; break; case 26: maybe_continue; if (which == &a[0]) maybe_continue; *which = 0xff; break; case 27: /* nop */ break; #endif default: if (k < 28) continue; if (no_sel) continue; if (which == &a[0]) maybe_continue; if (k < 34) { maybe_continue; unsigned int b[3] = {a[1], a[2], a[3]}; reorder(b, k - 28); *which = save_sel(b[0], b[1], b[2]); } else if (k < 40) { maybe_continue; if (!m) maybe_continue; unsigned int b[3] = {x, y, z}; reorder(b, j); reorder(b, k - 34); *which = save_sel(b[0], b[1], b[2]); } else { if (!m) maybe_continue; unsigned int b[3] = {a[1], a[2], a[3]}; reorder(b, (k - 40) % 6); a[1] = x; a[2] = y; a[3] = z; reorder(&a[1], (k - 40) / 6); *which = save_sel(b[0], b[1], b[2]); } } if (n && i) { unsigned int *d[2]; switch (i) { case 1: d[0] = &a[2]; d[1] = &a[3]; break; case 2: d[0] = &a[1]; d[1] = &a[3]; break; case 3: d[0] = &a[1]; d[1] = &a[2]; break; } switch ((n - 1) >> 1) { case 0: *d[n & 1] = *which; break; case 1: *d[n & 1] = x; break; case 2: *d[n & 1] = y; break; case 3: *d[n & 1] = z; break; } } if (which != &a[0]) a[0] = op(a[1], a[2], a[3], o); if (a[0] == 0xdead) continue; a[0] &= 0xff; if (!seen[a[0]]) { seen[a[0]] = 1; diff++; } #ifdef TRUTH printf("%02x\n", a[0]); #endif if (a[0] != (f(x, y, z) & 0xff)) continue; fprintf(stderr, "%u %u %u %u %u %u%s\n", o, n, m, k, j, i, how); } printf("%u\n", diff); return 0; }