#include #include #include #include "vm.h" // TODO: properly handle RETURN. // TODO: calling other functions in function /* ================================ vm_doOp(struct vm_Operation *op, int *orign_pos) Takes a vm_Operation and does the appropriate ops! Also takes an integer pointer(which indicates operation id) and: increments it for normal ops, double increments it if a conditional op is failed(to a JUMP), or a negative value for RETURN. Probably will change this. ================================ */ int vm_doOp(struct vm_Operation *op, int *orig_pos) { int op_pos = *orig_pos; //printf("0x%X: %d\n", op->pos_a, op->op); int val; switch(op->op) { case ASS_INT: memcpy(op->stack_a+op->pos_a, op->stack_b+op->pos_b, sizeof(int)); op_pos++; // move to next line break; case MIN_INT: val = *(int*)&(op->stack_a[op->pos_a]) - *(int*)&(op->stack_b[op->pos_b]); memcpy(op->stack_a+op->pos_a, &val, sizeof(int)); op_pos++; break; case ADD_INT: val = *(int*)&(op->stack_a[op->pos_a]) + *(int*)&(op->stack_b[op->pos_b]); memcpy(op->stack_a+op->pos_a, &val, sizeof(int)); op_pos++; break; case MUL_INT: val = *(int*)&(op->stack_a[op->pos_a]) * *(int*)&(op->stack_b[op->pos_b]); memcpy(op->stack_a+op->pos_a, &val, sizeof(int)); op_pos++; break; case DIV_INT: val = *(int*)&(op->stack_a[op->pos_a]) / *(int*)&(op->stack_b[op->pos_b]); memcpy(op->stack_a+op->pos_a, &val, sizeof(int)); op_pos++; break; case EQ_INT: if (*(int*)&(op->stack_a[op->pos_a]) == *(int*)&(op->stack_b[op->pos_b])) { op_pos += 2; // if true, we jump past the next op(which WILL be a jump) } else { op_pos++; // if false, move to next position which is a JUMP. } break; case LT_INT: if (*(int*)&(op->stack_a[op->pos_a]) < *(int*)&(op->stack_b[op->pos_b])) { op_pos += 2; // if true, we jump past the next op(which WILL be a jump) } else { op_pos++; // if false, move to next position which is a JUMP. } break; case LE_INT: if (*(int*)&(op->stack_a[op->pos_a]) <= *(int*)&(op->stack_b[op->pos_b])) { op_pos += 2; // if true, we jump past the next op(which WILL be a jump) } else { op_pos++; // if false, move to next position which is a JUMP. } break; case GT_INT: if (*(int*)&(op->stack_a[op->pos_a]) > *(int*)&(op->stack_b[op->pos_b])) { op_pos += 2; // if true, we jump past the next op(which WILL be a jump) } else { op_pos++; // if false, move to next position which is a JUMP. } break; case GE_INT: if (*(int*)&(op->stack_a[op->pos_a]) >= *(int*)&(op->stack_b[op->pos_b])) { op_pos += 2; // if true, we jump past the next op(which WILL be a jump) } else { op_pos++; // if false, move to next position which is a JUMP. } break; case JUMP: op_pos = (op->pos_a); break; case RETURN: printf("returning %d\n", *(int*)&op->stack_a[op->pos_a]); //op_pos = test_function.op_size; op_pos = -1; *orig_pos = op_pos; return (*(int*)&op->stack_a[op->pos_a]); break; default: // ERR break; } *orig_pos = op_pos; return 0; } /* ================================ vm_copyMem(struct vm_Stack *stack, int pos, void *from, int bytes) Copies /bytes/ from void pointer /from/ into memory offset /pos/ in /stack/. Used to avoid writing beyond the memory of the stack. ================================ */ void vm_copyMem(struct vm_Stack *stack, int pos, void *from, int bytes) { if (pos+bytes > stack->bytes) { printf("ERR: would overflow, not vm_copying\n"); } else { memcpy(stack->memory+pos, from, bytes); } } int main(int argc, char *argv[]) { struct vm_Function test_function; test_function.p_stack.memory = malloc(4); // 1 int parameter test_function.p_stack.bytes = 4; // allocate main stack (space for all variables - "var = 32" (var)) test_function.stack.memory = malloc(32); // 32 byte stack size test_function.stack.bytes = 32; // set up internal stack for right-hand ops such as "var = 32" (32) test_function.v_stack.memory = malloc(32); test_function.v_stack.bytes = 32; // we got 17 ops (not really) test_function.op_size = 17; test_function.ops = malloc(sizeof(struct vm_Operation)*17); // set our single parameters manually - this would be done in function call int num = 1; vm_copyMem(&test_function.p_stack, 0x00, &num, sizeof(int)); // manually set v_stack by copying num into 0x00 num = 2373; vm_copyMem(&test_function.v_stack, 0x00, &num, sizeof(int)); // copy v_stack[0x00] to stack[0x00] :) struct vm_Operation *set_op = &test_function.ops[0]; set_op->op = ASS_INT; set_op->stack_a = test_function.stack.memory; set_op->pos_a = 0x00; set_op->stack_b = test_function.v_stack.memory; set_op->pos_b = 0x00; num = 1; vm_copyMem(&test_function.v_stack, 0x04, &num, sizeof(int)); set_op = &test_function.ops[1]; set_op->op = ASS_INT; set_op->stack_a = test_function.stack.memory; set_op->pos_a = 0x04; set_op->stack_b = test_function.v_stack.memory; set_op->pos_b = 0x04; // begin while (0x04 < 0x00) { set_op = &test_function.ops[2]; set_op->op = LT_INT; set_op->stack_a = test_function.stack.memory; set_op->pos_a = 0x04; set_op->stack_b = test_function.stack.memory; set_op->pos_b = 0x00; // if not, jump to OP 6 set_op = &test_function.ops[3]; set_op->op = JUMP; set_op->stack_a = test_function.stack.memory; set_op->pos_a = 6; // otherwise, add parameter 2 set_op = &test_function.ops[4]; set_op->op = ADD_INT; set_op->stack_a = test_function.stack.memory; set_op->pos_a = 0x04; set_op->stack_b = test_function.p_stack.memory; set_op->pos_b = 0x00; // loop back to OP 2 (less than comparison) set_op = &test_function.ops[5]; set_op->op = JUMP; set_op->stack_a = test_function.stack.memory; set_op->pos_a = 2; // done with loop! return 0x04 :) set_op = &test_function.ops[6]; set_op->op = RETURN; set_op->stack_a = test_function.stack.memory; set_op->pos_a = 0x04; // Okay, this is where we actually run the above program int op_pos = 0; while(op_pos < test_function.op_size) { vm_doOp(&test_function.ops[op_pos], &op_pos); if (op_pos == -1) // return op_pos = test_function.op_size; } // dump stack memory :) int offset = 0; while(offset < test_function.stack.bytes) { printf("0x%X\n", offset); printf("\tint: %d, float: %f, char: %c\n", *(int*)(test_function.stack.memory+offset), *(float*)(test_function.stack.memory+offset), test_function.stack.memory[offset]); offset++; } return 0; }