/* * Team LemonLime's Universial Machine implementation. * Copyright (c) 2006, Michal Moskal, Bjorn Bringert and * Wouter Swierstra. */ #include #include #include #include #include #include typedef unsigned int uint; struct array *prog; uint exec; struct array { uint size; uint data[1]; }; void fatal(char *msg) { fprintf(stderr, "fatal: %s\n", msg); exit(3); } struct array *alloc(uint sz) { struct array *a = calloc(sz + 1, sizeof(uint)); if (a == NULL) fatal("out of malloc memory"); a->size = sz; return a; } struct array *get_array(uint x) { if (x == 0) { return prog; } else { return (struct array *)x; } } void run() { uint inst, a, b, c, op; uint regs[8] = { 0,0,0,0,0,0,0,0}; while (1) { if (exec >= prog->size) fatal("bad PC"); inst = prog->data[exec++]; c = inst & 7; b = (inst>>3) & 7; a = (inst>>6) & 7; op = inst >> 28; switch(op) { case 0: if (regs[c] != 0) regs[a] = regs[b]; break; case 1: regs[a] = get_array(regs[b])->data[regs[c]]; break; case 2: get_array(regs[a])->data[regs[b]] = regs[c]; break; case 3: regs[a] = regs[b] + regs[c]; break; case 4: regs[a] = regs[b] * regs[c]; break; case 5: if (regs[c] == 0) fatal("div by 0"); regs[a] = regs[b] / regs[c]; break; case 6: regs[a] = ~(regs[b] & regs[c]); break; case 7: exit(0); break; case 8: regs[b] = (uint)alloc(regs[c]); break; case 9: free(get_array(regs[c])); break; case 10: if (regs[c] > 255) fatal("big char"); putchar(regs[c]); break; case 11: regs[c] = getchar(); break; case 12: exec = regs[c]; if (regs[b] != 0) { free(prog); prog = alloc(get_array(regs[b])->size); memcpy(prog->data, get_array(regs[b])->data, prog->size * sizeof(uint)); } break; case 13: a = (inst >> 25) & 7; regs[a] = inst & 0x1ffffff; break; default: fatal("bad instr"); break; } } } int main(int argc, char *argv[]) { int ch1,ch2,ch3,ch4; int pos = 0; FILE *fprog; struct stat sb; if (argc != 2) { fprintf(stderr, "Usage vm \n"); exit(2); } fprog = fopen(argv[1], "rb"); fstat(fileno(fprog), &sb); prog = alloc(sb.st_size + 1); while(1) { ch1 = fgetc(fprog); if (ch1 == -1) break; ch2 = fgetc(fprog); ch3 = fgetc(fprog); ch4 = fgetc(fprog); assert(ch4!=-1); prog->data[pos] = (ch1<<24) | (ch2<<16) | (ch3<<8) | ch4; pos++; } prog->size = pos; run(); return 0; }