// opcodes static final int op_return = 0, op_nop = 1, op_jump = 2, op_jump_rel = 16, op_branchif = 3, op_branchifnot = 4, op_less = 5, op_less_im = 17, // highest op_equal = 6, op_more = 7, op_set = 8, op_set_ind = 9, op_copy = 10, op_copy_ind = 11, op_add = 12, op_add_im = 13, op_not = 14, op_neg = 15, op_illegal = 999; static int runProgram_maxSteps = 1000*1000; static void runProgram(Grid g, int pc) { new Runner(g, pc, runProgram_maxSteps); } sclass Runner { Grid g; int pc; *(Grid *g, int startAddress, int steps) { pc = startAddress; bool flag = false; for (int step = 0; step < steps; step++) { int opcode = g.get(pc++); int a, b; switch (opcode) { case op_return: ret; case op_nop: break; case op_jump: pc = g.get(pc); break; case op_jump_rel: pc += g.get(pc)-1; break; case op_branchif: if (flag) pc = g.get(pc); else ++pc; break; case op_branchifnot: if (!flag) pc = g.get(pc); else ++pc; break; case op_less: a = y(); b = y(); flag = a < b; break; case op_less_im: a = y(); b = x(); flag = a < b; break; case op_equal: a = y(); b = y(); flag = a == b; break; case op_more: a = y(); b = y(); flag = a > b; break; case op_set: a = x(); set(x(), a); break; case op_set_ind: a = x(); set(y(), a); break; case op_copy: a = y(); set(x(), a); break; case op_copy_ind: a = y(); set(y(), a); break; case op_add: a = x(); b = x(); set(a, get(a)+get(b)); break; case op_add_im: a = x(); b = x(); set(a, get(a)+b); break; case op_not: a = x(); set(a, ~get(a)); break; case op_neg: a = x(); set(a, -get(a)); default: fail("Illegal opcode " + opcode + " at " + (pc-1)); } } } int x() { ret get(pc++); } int y() { ret get(get(pc++)); } int get(int addr) { ret g.get(addr); } void set(int addr, int x) { g.set(addr, x); } } static void testProgram(Grid g, int startAddress, int... values) { runProgram(g, startAddress); for (int i = 0; i < l(values); i += 2) assertEquals(values[i+1], g.get(values[i])); //print("Program OK (" + n(l(program), "int") + ", " + n(l(values)/2, "value") + ")"); print("Program OK (" + n(l(values)/2, "value") + ")"); } static void disassemble(Grid g, int pc) { print(new Disassembler(g, pc).buf); } sclass Disassembler { Grid g; int pc; new StringBuffer buf; *(Grid *g, int startAddress) { pc = startAddress; int end = g.lastNonZero(); while (pc < end) { int opcode = g.get(pc++); int a, b; S s = "?"; switch (opcode) { case op_return: s = "return"; break; case op_nop: s = "nop"; break; case op_jump: s = "jump " + x(); break; case op_jump_rel: s = "jump rel " + x(); break; case op_branchif: s = "branch if " + x(); break; case op_branchifnot: s = "branch if not " + x(); break; case op_less: a = x(); b = x(); s = "less " + a + " " + b; break; case op_less_im: a = x(); b = x(); s = "less im " + a + " " + b; break; case op_equal: a = x(); b = x(); s = "equal " + a + " " + b; break; case op_more: a = x(); b = x(); s = "more " + a + " " + b; break; case op_set: a = x(); b = x(); s = "set " + a + " " + b; break; case op_set_ind: a = x(); b = x(); s = "set ind " + a + " " + b; break; case op_copy: a = x(); b = x(); s = "copy " + a + " " + b; break; case op_copy_ind: a = x(); b = x(); s = "copy ind " + a + " " + b; break; case op_add: a = x(); b = x(); s = "add " + a + " " + b; break; case op_add_im: a = x(); b = x(); s = "add im " + a + " " + b; break; case op_not: s = "not " + x(); break; case op_neg: s = "neg " + x(); default: s = "Unknown opcode " + opcode; } buf.append(s).append("\n"); } } int x() { ret g.get(pc++); } }