Fixed relative jumps back. Implemented CONCAT, GETY, GETZ, IN and OUT.

This commit is contained in:
2017-01-26 19:38:08 +01:00
parent af2d942005
commit a20dde4d5e
4 changed files with 53 additions and 18 deletions

View File

@@ -16,20 +16,20 @@ const bool stack_isfull(t_stack& stack) {
return stack.top == stack.max; 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)) { if (!stack_isfull(stack)) {
stack.data[++stack.top] = value; stack.data[++stack.top] = value;
} }
} }
const char stack_pop(t_stack& stack) { const unsigned char stack_pop(t_stack& stack) {
if (!stack_isempty(stack)) { if (!stack_isempty(stack)) {
return stack.data[stack.top--]; 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]; return stack.data[stack.top];
} }

View File

@@ -9,7 +9,7 @@ struct t_stack {
void stack_init(t_stack& stack, const int size); void stack_init(t_stack& stack, const int size);
const bool stack_isempty(t_stack& stack); const bool stack_isempty(t_stack& stack);
const bool stack_isfull(t_stack& stack); const bool stack_isfull(t_stack& stack);
void stack_push(t_stack& stack, const char value); void stack_push(t_stack& stack, const unsigned char value);
const char stack_pop(t_stack& stack); const unsigned char stack_pop(t_stack& stack);
const char stack_peek(t_stack& stack); const unsigned char stack_peek(t_stack& stack);
void stack_delete(t_stack& stack); void stack_delete(t_stack& stack);

47
vm.cpp
View File

@@ -4,6 +4,9 @@
#define MAX_DATA_STACK 256 #define MAX_DATA_STACK 256
#define MAX_CALL_STACK 256 #define MAX_CALL_STACK 256
typedef unsigned char byte;
typedef unsigned short word;
enum OPS { enum OPS {
OP_NOP = 0, OP_NOP = 0,
OP_PUSH, OP_PUSH,
@@ -21,6 +24,8 @@ enum OPS {
OP_SETX, OP_SETX,
OP_SETY, OP_SETY,
OP_SETZ, OP_SETZ,
OP_GETY,
OP_GETZ,
OP_INCX, OP_INCX,
OP_DECX, OP_DECX,
OP_INCY, OP_INCY,
@@ -62,6 +67,7 @@ enum OPS {
OP_NEG, OP_NEG,
OP_INC, OP_INC,
OP_DEC, OP_DEC,
OP_CONCAT,
OP_EQ, OP_EQ,
OP_NEQ, OP_NEQ,
@@ -69,12 +75,20 @@ enum OPS {
OP_GT, OP_GT,
OP_LEQ, OP_LEQ,
OP_GEQ, OP_GEQ,
OP_IN,
OP_OUT,
}; };
typedef void(*t_extcall)(t_stack&); typedef void(*t_extcall)(t_stack&);
t_extcall external_calls[MAX_EXTERNAL_CALLS]; t_extcall external_calls[MAX_EXTERNAL_CALLS];
int numcallbacks = 0; 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; const unsigned char* vm_program = nullptr;
int vm_pc = 0; int vm_pc = 0;
int vm_cycles = 0; int vm_cycles = 0;
@@ -112,6 +126,8 @@ void vm_step() {
case OP_SETX: rX = WORD(); vm_cycles++; break; case OP_SETX: rX = WORD(); vm_cycles++; break;
case OP_SETY: rY = stack_pop(vm_datastack); 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_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_INCX: rX++; vm_cycles++; break;
case OP_DECX: rX--; vm_cycles++; break; case OP_DECX: rX--; vm_cycles++; break;
case OP_INCY: rY++; 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_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_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_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_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_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_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]; 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_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_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_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]; 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_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_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_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]; 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_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_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; 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_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_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_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_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_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_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_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_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_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&)) { void vm_register_call(void(*callback)(t_stack&)) {
external_calls[numcallbacks++] = callback; 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;
}

2
vm.h
View File

@@ -4,3 +4,5 @@
void vm_init(const unsigned char* program); void vm_init(const unsigned char* program);
void vm_step(); void vm_step();
void vm_register_call(void(*callback)(t_stack&)); 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&));