diff --git a/stack.cpp b/stack.cpp index 91cf184..c70293d 100644 --- a/stack.cpp +++ b/stack.cpp @@ -16,20 +16,20 @@ const bool stack_isfull(t_stack& stack) { return stack.top == stack.max; } -void stack_push(t_stack& stack, const char value) { +void stack_push(t_stack& stack, const unsigned char value) { if (!stack_isfull(stack)) { stack.data[++stack.top] = value; } } -const char stack_pop(t_stack& stack) { +const unsigned char stack_pop(t_stack& stack) { if (!stack_isempty(stack)) { return stack.data[stack.top--]; } } -const char stack_peek(t_stack& stack) { +const unsigned char stack_peek(t_stack& stack) { return stack.data[stack.top]; } diff --git a/stack.h b/stack.h index f2e2a87..42c84a1 100644 --- a/stack.h +++ b/stack.h @@ -6,10 +6,10 @@ struct t_stack { int max{ 0 }; }; -void stack_init(t_stack& stack, const int size); -const bool stack_isempty(t_stack& stack); -const bool stack_isfull(t_stack& stack); -void stack_push(t_stack& stack, const char value); -const char stack_pop(t_stack& stack); -const char stack_peek(t_stack& stack); -void stack_delete(t_stack& stack); +void stack_init(t_stack& stack, const int size); +const bool stack_isempty(t_stack& stack); +const bool stack_isfull(t_stack& stack); +void stack_push(t_stack& stack, const unsigned char value); +const unsigned char stack_pop(t_stack& stack); +const unsigned char stack_peek(t_stack& stack); +void stack_delete(t_stack& stack); diff --git a/vm.cpp b/vm.cpp index 0a5bd21..488b181 100644 --- a/vm.cpp +++ b/vm.cpp @@ -4,6 +4,9 @@ #define MAX_DATA_STACK 256 #define MAX_CALL_STACK 256 +typedef unsigned char byte; +typedef unsigned short word; + enum OPS { OP_NOP = 0, OP_PUSH, @@ -21,6 +24,8 @@ enum OPS { OP_SETX, OP_SETY, OP_SETZ, + OP_GETY, + OP_GETZ, OP_INCX, OP_DECX, OP_INCY, @@ -62,6 +67,7 @@ enum OPS { OP_NEG, OP_INC, OP_DEC, + OP_CONCAT, OP_EQ, OP_NEQ, @@ -69,12 +75,20 @@ enum OPS { OP_GT, OP_LEQ, OP_GEQ, + + OP_IN, + OP_OUT, }; typedef void(*t_extcall)(t_stack&); t_extcall external_calls[MAX_EXTERNAL_CALLS]; int numcallbacks = 0; - + +typedef void(*t_out_port)(const byte&); +typedef byte(*t_in_port)(); +t_out_port out_ports[256]; +t_in_port in_ports[256]; + const unsigned char* vm_program = nullptr; int vm_pc = 0; int vm_cycles = 0; @@ -112,6 +126,8 @@ void vm_step() { 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_GETY: stack_push(vm_datastack, rY); vm_cycles++; break; + case OP_GETZ: stack_push(vm_datastack, rZ); vm_cycles++; break; case OP_INCX: rX++; vm_cycles++; break; case OP_DECX: rX--; vm_cycles++; break; case OP_INCY: rY++; vm_cycles++; break; @@ -125,19 +141,19 @@ void vm_step() { case OP_RET: rZ = stack_pop(vm_callstack); rY = stack_pop(vm_callstack); rX = (stack_pop(vm_callstack) << 8) + stack_pop(vm_callstack); 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_RJ: vm_pc += vm_program[vm_pc]; vm_cycles++; break; - case OP_RB: vm_pc -= vm_program[vm_pc]; vm_cycles++; break; + case OP_RB: vm_pc -= vm_program[vm_pc]+1; vm_cycles++; break; case OP_RJZ: if (stack_pop(vm_datastack) == 0) vm_pc += vm_program[vm_pc]; vm_cycles++; break; case OP_RJN: if (stack_pop(vm_datastack) != 0) vm_pc += vm_program[vm_pc]; vm_cycles++; break; - case OP_RBZ: if (stack_pop(vm_datastack) == 0) vm_pc -= vm_program[vm_pc]; vm_cycles++; break; - case OP_RBN: if (stack_pop(vm_datastack) != 0) vm_pc -= vm_program[vm_pc]; vm_cycles++; break; + case OP_RBZ: if (stack_pop(vm_datastack) == 0) vm_pc -= vm_program[vm_pc]+1; vm_cycles++; break; + case OP_RBN: if (stack_pop(vm_datastack) != 0) vm_pc -= vm_program[vm_pc]+1; 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_RBYZ: if (rY == 0) vm_pc -= vm_program[vm_pc]+1; vm_cycles++; break; + case OP_RBYN: if (rY != 0) vm_pc -= vm_program[vm_pc]+1; 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_RBZZ: if (rZ == 0) vm_pc -= vm_program[vm_pc]+1; vm_cycles++; break; + case OP_RBZN: if (rZ != 0) vm_pc -= vm_program[vm_pc]+1; 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; @@ -149,15 +165,32 @@ void vm_step() { 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_CONCAT: + val = stack_pop(vm_datastack); + for (int i = 0; i < val; i++) stack_push(vm_callstack, stack_pop(vm_datastack)); + val2 = stack_pop(vm_datastack); + for (int i = 0; i < val; i++) stack_push(vm_datastack, stack_pop(vm_callstack)); + stack_push(vm_datastack, val + val2); + 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; + case OP_IN: stack_push(vm_datastack, in_ports[vm_program[vm_pc++]]()); vm_cycles++; break; + case OP_OUT: out_ports[vm_program[vm_pc++]](stack_pop(vm_datastack)); vm_cycles++; break; } } void vm_register_call(void(*callback)(t_stack&)) { external_calls[numcallbacks++] = callback; } + +void vm_register_in_port(const byte port, t_in_port callback) { + in_ports[port] = callback; +} + +void vm_register_out_port(const byte port, t_out_port callback) { + out_ports[port] = callback; +} diff --git a/vm.h b/vm.h index adc7ff6..d402517 100644 --- a/vm.h +++ b/vm.h @@ -4,3 +4,5 @@ void vm_init(const unsigned char* program); void vm_step(); void vm_register_call(void(*callback)(t_stack&)); +void vm_register_in_port(const unsigned char port, unsigned char(*callback)(void)); +void vm_register_out_port(const unsigned char port, void(*callback)(const unsigned char&));