Fixed relative jumps back. Implemented CONCAT, GETY, GETZ, IN and OUT.
This commit is contained in:
@@ -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];
|
||||
}
|
||||
|
||||
|
||||
14
stack.h
14
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);
|
||||
|
||||
47
vm.cpp
47
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;
|
||||
}
|
||||
|
||||
2
vm.h
2
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&));
|
||||
|
||||
Reference in New Issue
Block a user