/* * JVM 00 (without methods, arrays, objects, floats) * 15-122 Principles of Imperative Computation, Fall 2010 * Frank Pfenning */ // cc0 -lconio -lfile -lstring -lparse elem.h0 lists.c0 stacks.c0 readfile.c0 jvm00.c0 struct func { int max_local; /* use V[0..max_local) */ int max_pc; /* use P[0..max_pc) */ int[] program; /* program P */ }; typedef struct func* func; int theint(string s) { struct parsed_int* pint = parse_int(s,16); assert(pint->parsed, "bad input file format"); return pint->value; } func read_program(string filename) { reader_t* r = get_reader(filename); int max_pc = theint(read_word(r)); int max_local = theint(read_word(r)); int[] P = alloc_array(int, max_pc); func f = alloc(struct func); int i; f->max_local = max_local; f->max_pc = max_pc; for (i = 0; i < max_pc; i++) P[i] = theint(read_word(r)); f->program = P; return f; } int offset(int o) { if (o > 127) return o-256; else return o; } int exec (func f, int arg1, int arg2) { int[] P = f->program; int[] V = alloc_array(int, f->max_local); stack S = s_new(); int pc = 0; V[1] = arg1; V[2] = arg2; while (true) { int inst = P[pc]; if (inst == 0x00) { pc+=1; } else if (inst == 0x60) { push(pop(S)+pop(S),S) ; pc+=1; } // iadd else if (inst == 0x64) { push(-(pop(S)-pop(S)),S) ; pc+=1; } // isub; unsafe for C else if (inst == 0x68) { push(pop(S)*pop(S),S) ; pc+=1; } // imul else if (inst == 0x6C) { int y = pop(S); int x = pop(S); push(x/y,S); pc+=1; } // idiv; unsafe for C else if (inst == 0xB1) { return pop(S); } // ireturn else if (inst == 0x59) { int x = pop(S); push(x,S); push(x,S); pc+=1; } // dup else if (inst == 0x57) { pop(S); pc+=1; } // pop else if (inst == 0x5F) { int x = pop(S); int y = pop(S); push(x,S); push(y,S); pc+=1; } // swap else if (inst == 0x10) { push(P[pc+1],S); pc+=2; } // bipush else if (inst == 0x15) { push(V[P[pc+1]],S); pc+=2; } // iload else if (inst == 0x36) { V[P[pc+1]] = pop(S); pc+=2; } // istore else if (inst == 0xA7) { pc += offset(P[pc+1]); } // goto else if (inst == 0x9F) { if (pop(S) == pop(S)) { pc += offset(P[pc+1]); } else { pc+=2; } } // if_icmpeq ; unsafe for C else if (inst == 0xA3) { if (pop(S) < pop(S)) { pc += offset(P[pc+1]); } else { pc+=2; } } // if_cmpgt ; unsafe for C else assert(false, "unrecognized instruction"); } assert(false, "should never reach this spot"); return 0; } int isqrt (int n) { int i = 0; int k = 0; while (k <= n) { k += 2*i + 1; i++; } return i-1; } void printres(int i, int k) { printint(i); print(" == "); printint(k); print("\n"); } int main () { func f = read_program("dsquared.hx"); printres(exec(f, 3, 4), 3*3+4*4); printres(exec(f, 25, 238), 25*25+238*238); f = read_program("isqrt.hx"); printres(exec(f, 26, 0), isqrt(26)); printres(exec(f, 283*283, 0), isqrt(283*283)); return 0; }