add call frames, refactor to allow call frames to work, add debug
This commit is contained in:
		
							parent
							
								
									f909071287
								
							
						
					
					
						commit
						aab4c887ca
					
				| 
						 | 
				
			
			@ -1,20 +1,8 @@
 | 
			
		|||
#include "compiler.h"
 | 
			
		||||
#include "parser.h"
 | 
			
		||||
 | 
			
		||||
#define MEMORY_SIZE 1024
 | 
			
		||||
 | 
			
		||||
Code *demo_add_compile() {
 | 
			
		||||
  Code *code = (Code *)malloc(sizeof(Code));
 | 
			
		||||
  Value memory[MEMORY_SIZE] = {0}; /* Memory array */
 | 
			
		||||
  code->memory = memory;
 | 
			
		||||
  code->size = MEMORY_SIZE;
 | 
			
		||||
  code->current.pc = 1;
 | 
			
		||||
 | 
			
		||||
  uint32_t i = 1;
 | 
			
		||||
  memory[0].c[0] = 0;
 | 
			
		||||
  memory[0].c[1] = 'z';
 | 
			
		||||
  memory[0].c[2] = 'r';
 | 
			
		||||
  memory[0].c[3] = 'e';
 | 
			
		||||
void demo_add_compile(Value *memory) {
 | 
			
		||||
  uint32_t i = 0;
 | 
			
		||||
  memory[i++].u = OP(OP_LOADU, 0, 0, 0);
 | 
			
		||||
  memory[i++].u = 0;
 | 
			
		||||
  memory[i++].u = OP(OP_LOADU, 1, 0, 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -43,26 +31,13 @@ Code *demo_add_compile() {
 | 
			
		|||
  memory[i++].u = OP(OP_READ_STRING, 7, 0, 0);
 | 
			
		||||
  memory[i++].u = OP(OP_PRINT_STRING, 0, 7, 0);
 | 
			
		||||
  memory[i++].u = OP(OP_HALT, 0, 0, 0);
 | 
			
		||||
 | 
			
		||||
  return code;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Code *compile(char *buffer) {
 | 
			
		||||
  Code *code = (Code *)malloc(sizeof(Code));
 | 
			
		||||
  Value memory[MEMORY_SIZE] = {0}; /* Memory array */
 | 
			
		||||
  code->memory = memory;
 | 
			
		||||
  code->size = MEMORY_SIZE;
 | 
			
		||||
 | 
			
		||||
  /* char number[100]; */
 | 
			
		||||
  memory[0].c[0] = 0;
 | 
			
		||||
  memory[0].c[1] = 'z';
 | 
			
		||||
  memory[0].c[2] = 'r';
 | 
			
		||||
  memory[0].c[3] = 'e';
 | 
			
		||||
 | 
			
		||||
void compile(Value *memory, char *buffer) {
 | 
			
		||||
  initTokenizer(buffer);
 | 
			
		||||
  Token t = nextToken();
 | 
			
		||||
  do {
 | 
			
		||||
    debug_printToken(t);
 | 
			
		||||
    printToken(t);
 | 
			
		||||
    switch (t.type) {
 | 
			
		||||
    case TOKEN_LEFT_PAREN:
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			@ -195,6 +170,4 @@ Code *compile(char *buffer) {
 | 
			
		|||
    }
 | 
			
		||||
    t = nextToken();
 | 
			
		||||
  } while (t.type != TOKEN_EOF);
 | 
			
		||||
 | 
			
		||||
  return code;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,14 +3,7 @@
 | 
			
		|||
 | 
			
		||||
#include "opcodes.h"
 | 
			
		||||
 | 
			
		||||
typedef struct Code Code;
 | 
			
		||||
struct Code {
 | 
			
		||||
  Value *memory; 
 | 
			
		||||
  uint32_t size;
 | 
			
		||||
  Frame current;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Code* demo_add_compile ();
 | 
			
		||||
Code* compile (char *buffer);
 | 
			
		||||
void demo_add_compile (Value* memory);
 | 
			
		||||
void compile (Value* memory, char *buffer);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										152
									
								
								src/debug.c
								
								
								
								
							
							
						
						
									
										152
									
								
								src/debug.c
								
								
								
								
							| 
						 | 
				
			
			@ -1,15 +1,15 @@
 | 
			
		|||
#include "debug.h"
 | 
			
		||||
 | 
			
		||||
int core_dump(Value *memory, uint32_t memory_size) {
 | 
			
		||||
int core_dump(VM *vm) {
 | 
			
		||||
  FILE *file = fopen("memory_dump.bin", "wb");
 | 
			
		||||
  if (!file) {
 | 
			
		||||
    perror("Failed to open file");
 | 
			
		||||
    return EXIT_FAILURE;
 | 
			
		||||
  }
 | 
			
		||||
  size_t written = fwrite(memory, 1, memory_size, file);
 | 
			
		||||
  if (written != memory_size) {
 | 
			
		||||
  size_t written = fwrite(vm->memory, 1, vm->memory_size, file);
 | 
			
		||||
  if (written != vm->memory_size) {
 | 
			
		||||
    fprintf(stderr, "Incomplete write: %zu bytes written out of %u\n", written,
 | 
			
		||||
            memory_size);
 | 
			
		||||
            vm->memory_size);
 | 
			
		||||
    fclose(file);
 | 
			
		||||
    return EXIT_FAILURE;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -17,3 +17,147 @@ int core_dump(Value *memory, uint32_t memory_size) {
 | 
			
		|||
  fclose(file);
 | 
			
		||||
  return EXIT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void printOp(uint8_t op, uint8_t dest, uint8_t src1, uint8_t src2) {
 | 
			
		||||
  switch (op) {
 | 
			
		||||
  case OP_HALT:
 | 
			
		||||
    printf("[HALT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_LOADI:
 | 
			
		||||
    printf("[LOADI] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_LOADU:
 | 
			
		||||
    printf("[LOADU] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_LOADF:
 | 
			
		||||
    printf("[LOADF] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_STOREI:
 | 
			
		||||
    printf("[STOREI] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_STOREU:
 | 
			
		||||
    printf("[STOREU] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_STOREF:
 | 
			
		||||
    printf("[STOREF] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_ADD_INT:
 | 
			
		||||
    printf("[ADD_INT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_SUB_INT:
 | 
			
		||||
    printf("[SUB_INT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_MUL_INT:
 | 
			
		||||
    printf("[MUL_INT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_DIV_INT:
 | 
			
		||||
    printf("[DIV_INT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JEQ_INT:
 | 
			
		||||
    printf("[JEQ_INT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JGT_INT:
 | 
			
		||||
    printf("[JGT_INT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JLT_INT:
 | 
			
		||||
    printf("[JLT_INT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JLE_INT:
 | 
			
		||||
    printf("[JLE_INT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JGE_INT:
 | 
			
		||||
    printf("[JGE_INT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_INT_TO_REAL:
 | 
			
		||||
    printf("[INT_TO_REAL] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_ADD_UINT:
 | 
			
		||||
    printf("[ADD_UINT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_SUB_UINT:
 | 
			
		||||
    printf("[SUB_UINT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_MUL_UINT:
 | 
			
		||||
    printf("[MUL_UINT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_DIV_UINT:
 | 
			
		||||
    printf("[DIV_UINT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JEQ_UINT:
 | 
			
		||||
    printf("[JEQ_UINT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JGT_UINT:
 | 
			
		||||
    printf("[JGT_UINT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JLT_UINT:
 | 
			
		||||
    printf("[JLT_UINT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JLE_UINT:
 | 
			
		||||
    printf("[JLE_UINT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JGE_UINT:
 | 
			
		||||
    printf("[JGE_UINT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_UINT_TO_REAL:
 | 
			
		||||
    printf("[UINT_TO_REAL] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_ADD_REAL:
 | 
			
		||||
    printf("[ADD_REAL] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_SUB_REAL:
 | 
			
		||||
    printf("[SUB_REAL] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_MUL_REAL:
 | 
			
		||||
    printf("[MUL_REAL] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_DIV_REAL:
 | 
			
		||||
    printf("[DIV_REAL] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JEQ_REAL:
 | 
			
		||||
    printf("[JEQ_REAL] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JGE_REAL:
 | 
			
		||||
    printf("[JGE_REAL] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JGT_REAL:
 | 
			
		||||
    printf("[JGT_REAL] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JLT_REAL:
 | 
			
		||||
    printf("[JLT_REAL] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JLE_REAL:
 | 
			
		||||
    printf("[JLE_REAL] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_REAL_TO_INT:
 | 
			
		||||
    printf("[REAL_TO_INT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_REAL_TO_UINT:
 | 
			
		||||
    printf("[REAL_TO_UINT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_MOV:
 | 
			
		||||
    printf("[MOV] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JMP:
 | 
			
		||||
    printf("[JMP] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_INT_TO_STRING:
 | 
			
		||||
    printf("[INT_TO_STRING] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_UINT_TO_STRING:
 | 
			
		||||
    printf("[UINT_TO_STRING] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_REAL_TO_STRING:
 | 
			
		||||
    printf("[REAL_TO_STRING] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_READ_STRING:
 | 
			
		||||
    printf("[READ_STRING] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_PRINT_STRING:
 | 
			
		||||
    printf("[PRINT_STRING] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_CMP_STRING:
 | 
			
		||||
    printf("[CMP_STRING] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,10 @@
 | 
			
		|||
#define ZRE_DEBUG_H
 | 
			
		||||
 | 
			
		||||
#include "vm.h"
 | 
			
		||||
#include "parser.h"
 | 
			
		||||
#include "opcodes.h"
 | 
			
		||||
 | 
			
		||||
int core_dump(Value *memory, uint32_t memory_size);
 | 
			
		||||
int core_dump(VM *vm);
 | 
			
		||||
void printOp(uint8_t op, uint8_t dest, uint8_t src1, uint8_t src2);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								src/main.c
								
								
								
								
							
							
						
						
									
										12
									
								
								src/main.c
								
								
								
								
							| 
						 | 
				
			
			@ -16,14 +16,14 @@
 | 
			
		|||
#include <emscripten.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
Code *code;
 | 
			
		||||
VM *vm;
 | 
			
		||||
 | 
			
		||||
void mainloop() {
 | 
			
		||||
  if (!step_vm(&code->current, code->memory)) {
 | 
			
		||||
  if (!step_vm(vm)) {
 | 
			
		||||
#ifdef __EMSCRIPTEN__
 | 
			
		||||
    emscripten_cancel_main_loop(); /* this should "kill" the app. */
 | 
			
		||||
#else
 | 
			
		||||
    core_dump(code->memory, code->size);
 | 
			
		||||
    core_dump(vm);
 | 
			
		||||
    exit(0);
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -50,8 +50,10 @@ int main(int argc, char **argv) {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  initTokenMap();
 | 
			
		||||
  compile(buffer);
 | 
			
		||||
  code = demo_add_compile();
 | 
			
		||||
  vm = init_vm();
 | 
			
		||||
  vm->frame = (Frame*)malloc(sizeof(Frame));
 | 
			
		||||
  compile(vm->memory, buffer);
 | 
			
		||||
  demo_add_compile(vm->memory);
 | 
			
		||||
 | 
			
		||||
#ifdef __EMSCRIPTEN__
 | 
			
		||||
  emscripten_set_main_loop(mainloop, 0, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,13 +10,29 @@ typedef union {
 | 
			
		|||
  char c[4];  /* 4 Byte char array for string packing */
 | 
			
		||||
} Value;
 | 
			
		||||
 | 
			
		||||
#define MAX_REGS 255
 | 
			
		||||
typedef union {
 | 
			
		||||
  uint32_t length;
 | 
			
		||||
  char *string;
 | 
			
		||||
  Value *array;
 | 
			
		||||
  Value *code;
 | 
			
		||||
} Object;
 | 
			
		||||
 | 
			
		||||
#define MAX_REGS 256
 | 
			
		||||
typedef struct {
 | 
			
		||||
  Value registers[MAX_REGS]; /* R0-R255 */
 | 
			
		||||
  uint32_t pc;               /* Program counter */
 | 
			
		||||
  Object *locals;            /* Short lived object */
 | 
			
		||||
} Frame;
 | 
			
		||||
 | 
			
		||||
#define STACK_SIZE 128
 | 
			
		||||
typedef struct {
 | 
			
		||||
  Value stack[STACK_SIZE]; 
 | 
			
		||||
  uint32_t stack_size;
 | 
			
		||||
  uint32_t pc;               /* Program counter */
 | 
			
		||||
  Value *memory; 
 | 
			
		||||
  uint32_t memory_size;
 | 
			
		||||
  Frame *frame;
 | 
			
		||||
} VM;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  OP_HALT,           /* terminate execution */
 | 
			
		||||
  OP_LOADI,          /* dest = next memory location as int */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -229,7 +229,8 @@ Token nextToken() {
 | 
			
		|||
  return errorToken("Unexpected character.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void debug_printToken(Token t) {
 | 
			
		||||
 | 
			
		||||
void printToken(Token t) {
 | 
			
		||||
  char *str = currentTokenToS();
 | 
			
		||||
 | 
			
		||||
  switch (t.type) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,7 +109,7 @@ struct TokenMap
 | 
			
		|||
 | 
			
		||||
void initTokenMap(); 
 | 
			
		||||
void initTokenizer (char *src);
 | 
			
		||||
void debug_printToken (Token t);
 | 
			
		||||
void printToken (Token t);
 | 
			
		||||
Token nextToken();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										149
									
								
								src/vm.c
								
								
								
								
							
							
						
						
									
										149
									
								
								src/vm.c
								
								
								
								
							| 
						 | 
				
			
			@ -1,18 +1,21 @@
 | 
			
		|||
#include "vm.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
 | 
			
		||||
#define COMPARE_AND_JUMP(type, accessor, op)                                   \
 | 
			
		||||
  do {                                                                         \
 | 
			
		||||
    type value = frame->registers[src1].accessor;                              \
 | 
			
		||||
    type value2 = frame->registers[src2].accessor;                             \
 | 
			
		||||
    frame->pc = (value op value2) ? dest : frame->pc;                          \
 | 
			
		||||
    return frame->pc;                                                          \
 | 
			
		||||
    type value = vm->frame->registers[src1].accessor;                          \
 | 
			
		||||
    type value2 = vm->frame->registers[src2].accessor;                         \
 | 
			
		||||
    vm->pc = (value op value2) ? dest : vm->pc;                                \
 | 
			
		||||
    return true;                                                             \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define MATH_OP(accessor, op)                                                  \
 | 
			
		||||
  do {                                                                         \
 | 
			
		||||
    frame->registers[dest].accessor =                                          \
 | 
			
		||||
        frame->registers[src1].accessor op frame->registers[src2].accessor;    \
 | 
			
		||||
    return frame->pc;                                                          \
 | 
			
		||||
    vm->frame->registers[dest].accessor =                                      \
 | 
			
		||||
        vm->frame->registers[src1]                                             \
 | 
			
		||||
            .accessor op vm->frame->registers[src2]                            \
 | 
			
		||||
            .accessor;                                                         \
 | 
			
		||||
    return true;                                                             \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -28,11 +31,23 @@ void mem_strcpy(Value *memory, const char *str, uint32_t length,
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MEMORY_SIZE 1024
 | 
			
		||||
 | 
			
		||||
VM *init_vm() {
 | 
			
		||||
  Value memory[MEMORY_SIZE] = {0}; /* Memory array */
 | 
			
		||||
  VM *vm = (VM *)malloc(sizeof(VM));
 | 
			
		||||
  vm->memory = memory;
 | 
			
		||||
  vm->memory_size = MEMORY_SIZE;
 | 
			
		||||
  vm->stack_size = 0;
 | 
			
		||||
 | 
			
		||||
  return vm;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Step to the next opcode in the vm.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t step_vm(Frame *frame, Value *memory) {
 | 
			
		||||
  uint32_t instruction = memory[frame->pc].u;
 | 
			
		||||
bool step_vm(VM *vm) {
 | 
			
		||||
  uint32_t instruction = vm->memory[vm->pc].u;
 | 
			
		||||
 | 
			
		||||
  /* Extract 8-bit register indices from 32-bit instruction */
 | 
			
		||||
  uint8_t opcode = (instruction >> 24) & 0xFF;
 | 
			
		||||
| 
						 | 
				
			
			@ -40,29 +55,31 @@ uint32_t step_vm(Frame *frame, Value *memory) {
 | 
			
		|||
  uint8_t src1 = (instruction >> 8) & 0xFF;
 | 
			
		||||
  uint8_t src2 = instruction & 0xFF;
 | 
			
		||||
  /* Advance to next instruction */
 | 
			
		||||
  frame->pc++;
 | 
			
		||||
  vm->pc++;
 | 
			
		||||
 | 
			
		||||
  printOp(opcode, dest, src1, src2);
 | 
			
		||||
 | 
			
		||||
  switch (opcode) {
 | 
			
		||||
  case OP_HALT:
 | 
			
		||||
    return 0;
 | 
			
		||||
    return false;
 | 
			
		||||
  case OP_LOADI:
 | 
			
		||||
    frame->registers[dest].i = memory[frame->pc++].i;
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->frame->registers[dest].i = vm->memory[vm->pc++].i;
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_LOADU:
 | 
			
		||||
    frame->registers[dest].u = memory[frame->pc++].u;
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->frame->registers[dest].u = vm->memory[vm->pc++].u;
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_LOADF:
 | 
			
		||||
    frame->registers[dest].f = memory[frame->pc++].f;
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->frame->registers[dest].f = vm->memory[vm->pc++].f;
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_STOREI:
 | 
			
		||||
    memory[frame->pc++].i = frame->registers[src1].i;
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->memory[vm->pc++].i = vm->frame->registers[src1].i;
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_STOREU:
 | 
			
		||||
    memory[frame->pc++].u = frame->registers[src1].u;
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->memory[vm->pc++].u = vm->frame->registers[src1].u;
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_STOREF:
 | 
			
		||||
    memory[frame->pc++].f = frame->registers[src1].f;
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->memory[vm->pc++].f = vm->frame->registers[src1].f;
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_ADD_INT:
 | 
			
		||||
    MATH_OP(i, +);
 | 
			
		||||
  case OP_SUB_INT:
 | 
			
		||||
| 
						 | 
				
			
			@ -88,23 +105,23 @@ uint32_t step_vm(Frame *frame, Value *memory) {
 | 
			
		|||
  case OP_DIV_REAL:
 | 
			
		||||
    MATH_OP(f, /);
 | 
			
		||||
  case OP_REAL_TO_INT:
 | 
			
		||||
    frame->registers[dest].i = (int32_t)(frame->registers[src1].f);
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->frame->registers[dest].i = (int32_t)(vm->frame->registers[src1].f);
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_INT_TO_REAL:
 | 
			
		||||
    frame->registers[dest].f = (float)(frame->registers[src1].i);
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->frame->registers[dest].f = (float)(vm->frame->registers[src1].i);
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_REAL_TO_UINT:
 | 
			
		||||
    frame->registers[dest].u = (uint32_t)(frame->registers[src1].f);
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->frame->registers[dest].u = (uint32_t)(vm->frame->registers[src1].f);
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_UINT_TO_REAL:
 | 
			
		||||
    frame->registers[dest].f = (float)(frame->registers[src1].u);
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->frame->registers[dest].f = (float)(vm->frame->registers[src1].u);
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_MOV:
 | 
			
		||||
    frame->registers[dest] = frame->registers[src1];
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->frame->registers[dest] = vm->frame->registers[src1];
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_JMP:
 | 
			
		||||
    frame->pc = frame->registers[src1].u; /* Jump to address */
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->pc = vm->frame->registers[src1].u; /* Jump to address */
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_JEQ_UINT: {
 | 
			
		||||
    COMPARE_AND_JUMP(uint32_t, u, ==);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -151,64 +168,64 @@ uint32_t step_vm(Frame *frame, Value *memory) {
 | 
			
		|||
    COMPARE_AND_JUMP(float, u, <=);
 | 
			
		||||
  }
 | 
			
		||||
  case OP_INT_TO_STRING: {
 | 
			
		||||
    int32_t a = (int32_t)frame->registers[src1].i;
 | 
			
		||||
    uint32_t str_dest = (uint32_t)frame->registers[dest].u;
 | 
			
		||||
    int32_t a = (int32_t)vm->frame->registers[src1].i;
 | 
			
		||||
    uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u;
 | 
			
		||||
    char buffer[32];
 | 
			
		||||
    int len = sprintf(buffer, "%d", a);
 | 
			
		||||
    mem_strcpy(memory, buffer, len, str_dest);
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    mem_strcpy(vm->memory, buffer, len, str_dest);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  case OP_UINT_TO_STRING: {
 | 
			
		||||
    uint32_t a = (uint32_t)frame->registers[src1].u;
 | 
			
		||||
    uint32_t str_dest = (uint32_t)frame->registers[dest].u;
 | 
			
		||||
    uint32_t a = (uint32_t)vm->frame->registers[src1].u;
 | 
			
		||||
    uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u;
 | 
			
		||||
    char buffer[32];
 | 
			
		||||
    int len = sprintf(buffer, "%d", a);
 | 
			
		||||
    mem_strcpy(memory, buffer, len, str_dest);
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    mem_strcpy(vm->memory, buffer, len, str_dest);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  case OP_REAL_TO_STRING: {
 | 
			
		||||
    float a = (float)frame->registers[src1].f;
 | 
			
		||||
    uint32_t str_dest = (uint32_t)frame->registers[dest].u;
 | 
			
		||||
    float a = (float)vm->frame->registers[src1].f;
 | 
			
		||||
    uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u;
 | 
			
		||||
    char buffer[32];
 | 
			
		||||
    int len = sprintf(buffer, "%f", a);
 | 
			
		||||
    mem_strcpy(memory, buffer, len, str_dest);
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    mem_strcpy(vm->memory, buffer, len, str_dest);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  case OP_READ_STRING: {
 | 
			
		||||
    uint32_t str_dest = (uint32_t)frame->registers[dest].u;
 | 
			
		||||
    uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u;
 | 
			
		||||
    uint32_t buffer = str_dest + 1;
 | 
			
		||||
    uint32_t length = 0;
 | 
			
		||||
    while (1) {
 | 
			
		||||
      int ch = getchar();
 | 
			
		||||
      if (ch == '\n' || ch == EOF) {
 | 
			
		||||
        memory[buffer + (length / 4)].c[length % 4] = '\0';
 | 
			
		||||
        vm->memory[buffer + (length / 4)].c[length % 4] = '\0';
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      memory[buffer + (length / 4)].c[length % 4] = ch;
 | 
			
		||||
      vm->memory[buffer + (length / 4)].c[length % 4] = ch;
 | 
			
		||||
      length++;
 | 
			
		||||
    }
 | 
			
		||||
    memory[str_dest].u = length;
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->memory[str_dest].u = length;
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  case OP_PRINT_STRING: {
 | 
			
		||||
    uint32_t ptr = (uint32_t)frame->registers[src1].u;
 | 
			
		||||
    uint32_t length = memory[ptr].u;
 | 
			
		||||
    uint32_t ptr = (uint32_t)vm->frame->registers[src1].u;
 | 
			
		||||
    uint32_t length = vm->memory[ptr].u;
 | 
			
		||||
    uint32_t str_src = ptr + 1;
 | 
			
		||||
    uint32_t i;
 | 
			
		||||
    for (i = 0; i < length; i++) {
 | 
			
		||||
      uint8_t ch = memory[str_src + (i / 4)].c[i % 4];
 | 
			
		||||
      uint8_t ch = vm->memory[str_src + (i / 4)].c[i % 4];
 | 
			
		||||
      if (ch == '\0')
 | 
			
		||||
        break;
 | 
			
		||||
      putchar(ch);
 | 
			
		||||
    }
 | 
			
		||||
    putchar('\n');
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  case OP_CMP_STRING: {
 | 
			
		||||
    uint32_t addr1 = (uint32_t)frame->registers[src1].u;
 | 
			
		||||
    uint32_t addr2 = (uint32_t)frame->registers[src2].u;
 | 
			
		||||
    uint32_t length1 = memory[addr1 - 1].u;
 | 
			
		||||
    uint32_t length2 = memory[addr2 - 1].u;
 | 
			
		||||
    uint32_t addr1 = (uint32_t)vm->frame->registers[src1].u;
 | 
			
		||||
    uint32_t addr2 = (uint32_t)vm->frame->registers[src2].u;
 | 
			
		||||
    uint32_t length1 = vm->memory[addr1 - 1].u;
 | 
			
		||||
    uint32_t length2 = vm->memory[addr2 - 1].u;
 | 
			
		||||
    uint32_t equal = 1;
 | 
			
		||||
 | 
			
		||||
    if (length1 != length2) {
 | 
			
		||||
| 
						 | 
				
			
			@ -216,19 +233,19 @@ uint32_t step_vm(Frame *frame, Value *memory) {
 | 
			
		|||
    } else {
 | 
			
		||||
      uint32_t i = 0;
 | 
			
		||||
      while (i < length1) {
 | 
			
		||||
        uint32_t char1 = memory[addr1 + i].u;
 | 
			
		||||
        uint32_t char2 = memory[addr2 + i].u;
 | 
			
		||||
        uint32_t char1 = vm->memory[addr1 + i].u;
 | 
			
		||||
        uint32_t char2 = vm->memory[addr2 + i].u;
 | 
			
		||||
        if (char1 != char2) {
 | 
			
		||||
          equal = 0;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        if ((char1 & 0xFF) == '\0' && (char2 & 0xFF) == '\0')
 | 
			
		||||
          return frame->pc;
 | 
			
		||||
          return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    memory[dest].u = equal;
 | 
			
		||||
    return frame->pc;
 | 
			
		||||
    vm->memory[dest].u = equal;
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  }
 | 
			
		||||
  return 0;
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue