#include #include #include #include #include #include #include #include #include // begin C++ pain #include using namespace std; #define A(inst) ((inst >> 0x6) & 0x7) #define B(inst) ((inst >> 0x3) & 0x7) #define C(inst) (inst & 0x7) #define A13(inst) ((inst >> 25) & 0x7) #define DATA(inst) (inst & 0x1ffffff) #define OP(inst) (inst >> 28) #define REG(num) (registers[num]) #define REGA(inst) (REG(A(inst))) #define REGB(inst) (REG(B(inst))) #define REGC(inst) (REG(C(inst))) #define REGA13(inst) (REG(A13(inst))) #define MEMSIZ (1024 * 1024 * 32) typedef unsigned int platter; platter registers[8] = {0,0,0,0,0,0,0,0}; platter * arrays[MEMSIZ]; size_t siz_arrays[MEMSIZ]; size_t num_array = 1; platter finger = 0; int last_free = 0; int main(int argc, char *argv[]) { int lastloc = 0, i; platter cur; platter * temp; struct stat x; queue free_list; stat(argv[1], &x); temp = (platter *) mmap(NULL, x.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, open(argv[1], O_RDONLY, 0600), (off_t) 0); arrays[0] = (platter *) malloc(x.st_size); memcpy(arrays[0], temp, x.st_size); munmap(temp, x.st_size); siz_arrays[0] = x.st_size; while(1) { cur = htonl(arrays[0][finger++]); switch(OP(cur)) { // condmove case 0: if (REGC(cur) != 0) { REGA(cur) = REGB(cur); } break; // index case 1: REGA(cur) = arrays[REGB(cur)][REGC(cur)]; break; // amend case 2: assert(arrays[REGA(cur)] != 0); arrays[REGA(cur)][REGB(cur)] = REGC(cur); break; // add case 3: REGA(cur) = REGB(cur) + REGC(cur); break; // mult case 4: REGA(cur) = REGB(cur) * REGC(cur); break; // div case 5: REGA(cur) = REGB(cur) / REGC(cur); break; // not_and case 6: REGA(cur) = ~ (REGB(cur) & REGC(cur)); break; // halt case 7: exit(0); break; // alloc case 8: // try and pop a location off the stack, otherwise start counting up if (!free_list.empty()) { i = free_list.front(); free_list.pop(); } else { for (i = lastloc+1; arrays[i] != NULL && i != lastloc; i = (i + 1) % MEMSIZ) ; } // this tracks the last insertion instead /* for (i = last_free; arrays[i] != NULL && i != last_free-1; i = (i + 1) % MEMSIZ) ; */ // this version walks forward in the array /* for (i = lastloc+1; arrays[i] != NULL && i != lastloc; i = (i + 1) % MEMSIZ) ; */ //assert(i != lastloc); //assert(i != last_free-1); // move last_free somewhere random, for fun //last_free = rand() % MEMSIZ; lastloc = i; arrays[i] = (platter *) calloc(REGC(cur), sizeof(platter)); siz_arrays[i] = REGC(cur); REGB(cur) = i; break; // abandon case 9: free(arrays[REGC(cur)]); arrays[REGC(cur)] = 0; //last_free = REGC(cur); free_list.push(REGC(cur)); break; // out case 10: if (REGC(cur) < 256) { putchar(REGC(cur)); fflush(stdout); } break; // in case 11: REGC(cur) = getchar(); break; // load case 12: if (REGB(cur) != 0) { free(arrays[0]); arrays[0] = (platter *) calloc(siz_arrays[REGB(cur)], sizeof(platter)); assert(arrays[0] != 0); assert(arrays[REGB(cur)] != 0); memcpy(arrays[0], arrays[REGB(cur)], siz_arrays[REGB(cur)] * sizeof(platter)); siz_arrays[0] = siz_arrays[REGB(cur)]; } finger = REGC(cur); break; // data case 13: REGA13(cur) = DATA(cur); break; default: fprintf(stderr, "Died!\n"); exit(1); } } }