diff --git a/vm.cpp b/vm.cpp index c98122a..81c2d77 100644 --- a/vm.cpp +++ b/vm.cpp @@ -15,6 +15,18 @@ enum OPS { OP_STORE, OP_STOREI, + OP_LOADXY, + OP_STOREXY, + OP_SETX, + OP_SETY, + OP_SETZ, + OP_INCX, + OP_DECX, + OP_INCY, + OP_DECY, + OP_INCZ, + OP_DECZ, + OP_JMP, OP_JNT, OP_JTR, @@ -22,6 +34,15 @@ enum OPS { OP_RET, OP_CALL, + OP_RJYZ, + OP_RJYN, + OP_RBYZ, + OP_RBYN, + OP_RJZZ, + OP_RJZN, + OP_RBZZ, + OP_RBZN, + OP_ADD, OP_SUB, OP_MUL, @@ -32,11 +53,14 @@ enum OPS { OP_NOT, OP_NEG, OP_INC, + OP_DEC, OP_EQ, OP_NEQ, OP_LT, - OP_GT + OP_GT, + OP_LEQ, + OP_GEQ, }; typedef void(*t_extcall)(t_stack&); @@ -49,10 +73,14 @@ int vm_cycles = 0; t_stack vm_datastack; t_stack vm_callstack; unsigned char mem[65536]; +unsigned short rX = 0; +unsigned char rY = 0; +unsigned char rZ = 0; + void vm_init(const unsigned char* program) { vm_program = program; - vm_pc = 0; + vm_pc = rX = rY = rZ = 0; stack_init(vm_datastack, MAX_DATA_STACK); stack_init(vm_callstack, MAX_CALL_STACK); } @@ -67,15 +95,34 @@ void vm_step() { case OP_POP: stack_pop(vm_datastack); vm_cycles++; break; case OP_DUP: stack_push(vm_datastack, stack_peek(vm_datastack)); vm_cycles++; break; case OP_LOAD: stack_push(vm_datastack, mem[WORD()]); vm_cycles++; break; - case OP_LOADI: stack_push(vm_datastack, mem[WORD() + stack_pop(vm_datastack)]); vm_cycles++; break; + case OP_LOADI: stack_push(vm_datastack, mem[WORD() + rY]); vm_cycles++; break; case OP_STORE: mem[WORD()] = stack_pop(vm_datastack); vm_cycles++; break; - case OP_STOREI: val = stack_pop(vm_datastack); mem[WORD() + stack_pop(vm_datastack)] = val; vm_cycles++; break; + case OP_STOREI: val = stack_pop(vm_datastack); mem[WORD() + rY] = val; vm_cycles++; break; + case OP_LOADXY: stack_push(vm_datastack, mem[rX + rY]); vm_cycles++; break; + case OP_STOREXY: mem[rX + rY] = stack_pop(vm_datastack); vm_cycles++; break; + case OP_SETX: rX = WORD(); vm_cycles++; break; + case OP_SETY: rY = stack_pop(vm_datastack); vm_cycles++; break; + case OP_SETZ: rZ = stack_pop(vm_datastack); vm_cycles++; break; + case OP_INCX: rX++; vm_cycles++; break; + case OP_DECX: rX--; vm_cycles++; break; + case OP_INCY: rY++; vm_cycles++; break; + case OP_DECY: rY--; vm_cycles++; break; + case OP_INCZ: rZ++; vm_cycles++; break; + case OP_DECZ: rZ--; vm_cycles++; break; case OP_JMP: vm_pc = WORD(); vm_cycles++; break; case OP_JNT: if (stack_pop(vm_datastack) == 0) { vm_pc = WORD(); } vm_cycles++; break; case OP_JTR: if (stack_pop(vm_datastack) != 0) { vm_pc = WORD(); } vm_cycles++; break; case OP_JSR: stack_push(vm_callstack, vm_pc+2); vm_pc = WORD(); vm_cycles++; break; case OP_RET: vm_pc = stack_pop(vm_callstack); vm_cycles++; break; case OP_CALL: external_calls[vm_program[vm_pc++]](vm_datastack); vm_cycles++; break; + case OP_RJYZ: if (rY == 0) vm_pc += vm_program[vm_pc]; vm_cycles++; break; + case OP_RJYN: if (rY != 0) vm_pc += vm_program[vm_pc]; vm_cycles++; break; + case OP_RBYZ: if (rY == 0) vm_pc -= vm_program[vm_pc]; vm_cycles++; break; + case OP_RBYN: if (rY != 0) vm_pc -= vm_program[vm_pc]; vm_cycles++; break; + case OP_RJZZ: if (rZ == 0) vm_pc += vm_program[vm_pc]; vm_cycles++; break; + case OP_RJZN: if (rZ != 0) vm_pc += vm_program[vm_pc]; vm_cycles++; break; + case OP_RBZZ: if (rZ == 0) vm_pc -= vm_program[vm_pc]; vm_cycles++; break; + case OP_RBZN: if (rZ != 0) vm_pc -= vm_program[vm_pc]; vm_cycles++; break; case OP_ADD: stack_push(vm_datastack, stack_pop(vm_datastack) + stack_pop(vm_datastack)); vm_cycles++; break; case OP_SUB: stack_push(vm_datastack, stack_pop(vm_datastack) - stack_pop(vm_datastack)); vm_cycles++; break; case OP_MUL: stack_push(vm_datastack, stack_pop(vm_datastack) * stack_pop(vm_datastack)); vm_cycles++; break; @@ -86,10 +133,13 @@ void vm_step() { case OP_NOT: stack_push(vm_datastack, !stack_pop(vm_datastack)); vm_cycles++; break; case OP_NEG: stack_push(vm_datastack, -stack_pop(vm_datastack)); vm_cycles++; break; case OP_INC: stack_push(vm_datastack, stack_pop(vm_datastack)+1); vm_cycles++; break; + case OP_DEC: stack_push(vm_datastack, stack_pop(vm_datastack) - 1); vm_cycles++; break; case OP_EQ: stack_push(vm_datastack, stack_pop(vm_datastack) == stack_pop(vm_datastack)); vm_cycles++; break; case OP_NEQ: stack_push(vm_datastack, stack_pop(vm_datastack) != stack_pop(vm_datastack)); vm_cycles++; break; case OP_LT: stack_push(vm_datastack, stack_pop(vm_datastack) < stack_pop(vm_datastack)); vm_cycles++; break; case OP_GT: stack_push(vm_datastack, stack_pop(vm_datastack) > stack_pop(vm_datastack)); vm_cycles++; break; + case OP_LEQ: stack_push(vm_datastack, stack_pop(vm_datastack) <= stack_pop(vm_datastack)); vm_cycles++; break; + case OP_GEQ: stack_push(vm_datastack, stack_pop(vm_datastack) >= stack_pop(vm_datastack)); vm_cycles++; break; } }