12 void debug(const char *fmt
, ...) {
14 if (getenv("DEBUG")) {
16 vfprintf(stderr
, fmt
, ap
);
21 static int16_t regs
[4];
22 static uint16_t possible
[16];
23 static char known
[16];
25 static int get(int r
) {
26 assert(0 <= r
&& r
< sizeof regs
/ sizeof *regs
);
30 static void set(int r
, int v
) {
31 assert(0 <= r
&& r
< sizeof regs
/ sizeof *regs
);
33 assert(regs
[r
] == v
|| !"resize regs to be larger type");
36 static const char *step(int op
, int a
, int b
, int c
) {
39 set(c
, get(a
) + get(b
)); return "addr";
41 set(c
, get(a
) + b
); return "addi";
43 set(c
, get(a
) * get(b
)); return "mulr";
45 set(c
, get(a
) * b
); return "muli";
47 set(c
, get(a
) & get(b
)); return "banr";
49 set(c
, get(a
) & b
); return "bani";
51 set(c
, get(a
) | get(b
)); return "borr";
53 set(c
, get(a
) | b
); return "bori";
55 set(c
, get(a
)); return "setr";
57 set(c
, a
); return "seti";
59 set(c
, a
> get(b
)); return "gtir";
61 set(c
, get(a
) > b
); return "gtri";
63 set(c
, get(a
) > get(b
)); return "gtrr";
65 set(c
, a
== get(b
)); return "eqir";
67 set(c
, get(a
) == b
); return "eqri";
69 set(c
, get(a
) == get(b
)); return "eqrr";
75 static int try(int b0
, int b1
, int b2
, int b3
, int op
, int a
, int b
, int c
,
76 int a0
, int a1
, int a2
, int a3
) {
78 const char *str
= NULL
;
79 debug("Want %d %d %d %d into %d %d %d %d given %d %d %d\n",
80 b0
, b1
, b2
, b3
, a0
, a1
, a2
, a3
, a
, b
, c
);
81 for (int i
= 0; i
< 16; i
++) {
86 const char *tmp
= step(i
, a
, b
, c
);
87 debug("op %2d converted to %d %d %d %d", i
,
88 regs
[0], regs
[1], regs
[2], regs
[3]);
89 if (regs
[0] == a0
&& regs
[1] == a1
&& regs
[2] == a2
&& regs
[3] == a3
) {
90 debug(", matching %s\n", str
= tmp
);
94 possible
[op
] &= ~(1 << i
);
97 debug("%d possible ops as decode\n", r
);
101 int main(int argc
, char **argv
) {
102 size_t len
= 0, count
= 0;
109 bool reduced
= false;
111 /* Part 1 - read in samples */
112 memset(possible
, -1, sizeof possible
);
113 memset(known
, -1, sizeof known
);
114 if (argc
> 1 && !(stdin
= freopen(argv
[1], "r", stdin
))) {
120 if (getline(&line
, &len
, stdin
) <= 0)
122 if (sscanf(line
, "Before: [%1d, %1d, %1d, %1d]\n",
123 &b0
, &b1
, &b2
, &b3
) != 4)
126 if (getline(&line
, &len
, stdin
) <= 0)
128 if (sscanf(line
, "%d %d %d %d\n", &op
, &a
, &b
, &c
) != 4)
131 if (getline(&line
, &len
, stdin
) <= 0)
133 if (sscanf(line
, "After: [%1d, %1d, %1d, %1d]\n",
134 &a0
, &a1
, &a2
, &a3
) != 4)
137 if (getline(&line
, &len
, stdin
) < 0)
140 if (try(b0
, b1
, b2
, b3
, op
, a
, b
, c
, a0
, a1
, a2
, a3
) >= 3)
144 printf("%zu stanzas read, found %d states with 3+ opcodes\n", count
, ret
);
146 /* Part 2 - decode */
147 for (i
= 0; i
< 16; i
++)
148 printf("op %2d could be %04x\n", i
, possible
[i
]);
149 printf("Reducing possible...\n");
152 for (i
= 0; i
< 16; i
++) {
153 if (known
[i
] != -1 || (possible
[i
] & (possible
[i
] - 1)))
156 known
[i
] = log2(possible
[i
]);
157 printf("op %d is %s\n", i
, step(known
[i
], 0, 0, 0));
158 for (j
= 0; j
< 16; j
++)
160 possible
[j
] &= ~possible
[i
& 0xf];
164 /* Part 3 - run program */
165 memset(regs
, 0, sizeof regs
);
168 if (getline(&line
, &len
, stdin
) < 0)
173 if (sscanf(line
, "%d %d %d %d\n", &op
, &a
, &b
, &c
) != 4)
175 step(known
[op
], a
, b
, c
);
177 printf("After %zu instructions, reg 0 contains %d\n", count
, regs
[0]);