207 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			207 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| #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;
 | |
| }
 |