add initial stuff, is very broken because of overflows
This commit is contained in:
		
							parent
							
								
									039aa7e9f9
								
							
						
					
					
						commit
						f476b74c3f
					
				
							
								
								
									
										123
									
								
								src/opcodes.h
								
								
								
								
							
							
						
						
									
										123
									
								
								src/opcodes.h
								
								
								
								
							| 
						 | 
					@ -2,69 +2,70 @@
 | 
				
			||||||
#define ZRL_OPCODES_H
 | 
					#define ZRL_OPCODES_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "common.h"
 | 
					#include "common.h"
 | 
				
			||||||
 | 
					#include "fixed.h"
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
  OP_HALT,   /* halt : terminate execution */
 | 
					  OP_HALT,          /* halt : terminate execution */
 | 
				
			||||||
  OP_JMP,    /* jump : jump to address dest unconditionally */
 | 
					  OP_JMP,           /* jump : jump to address dest unconditionally */
 | 
				
			||||||
  OP_GET_PC, /* pc   : dest = current program counter */
 | 
					  OP_GET_PC,        /* pc   : dest = current program counter */
 | 
				
			||||||
  OP_CALL,   /* call : creates a new frame */
 | 
					  OP_CALL,          /* call : creates a new frame */
 | 
				
			||||||
  OP_RETURN, /* retn : returns from a frame to the parent frame */
 | 
					  OP_RETURN,        /* retn : returns from a frame to the parent frame */
 | 
				
			||||||
  OP_LOAD,   /* load : dest = &[next memory location] */
 | 
					  OP_LOAD,          /* load : dest = &[next code location] */
 | 
				
			||||||
  OP_STORE,  /* stor : next memory location = src1 as float */
 | 
					  OP_STORE,         /* stor : next code location = src1 as float */
 | 
				
			||||||
  OP_PUSH, /* push : push str ref from register onto the stack and copy str  */
 | 
					  OP_PUSH,          /* push : push str ref from register onto the stack and copy str  */
 | 
				
			||||||
  OP_POP,  /* pop  : pop int from stack onto the register */
 | 
					  OP_POP,           /* pop  : pop int from stack onto the register */
 | 
				
			||||||
  OP_REG_MOV,      /* rmov : dest = src1	   */
 | 
					  OP_REG_MOV,       /* rmov : dest = src1	   */
 | 
				
			||||||
  OP_REG_SWAP,     /* rswp : dest = src1, src1 = dest	   */
 | 
					  OP_REG_SWAP,      /* rswp : dest = src1, src1 = dest	   */
 | 
				
			||||||
  OP_GET_ACC,      /* gacc : dest = accumulator */
 | 
					  OP_GET_ACC,       /* gacc : dest = accumulator */
 | 
				
			||||||
  OP_MEM_SWAP,     /* mswp : &dest = &src1, &src1 = &dest */
 | 
					  OP_MEM_SWAP,      /* mswp : &dest = &src1, &src1 = &dest */
 | 
				
			||||||
  OP_MEM_MOV,      /* mmov : &dest = &src1 */
 | 
					  OP_MEM_MOV,       /* mmov : &dest = &src1 */
 | 
				
			||||||
  OP_MEM_ALLOC,    /* aloc : dest [next memory location as size] */
 | 
					  OP_MEM_ALLOC,     /* aloc : dest [next memory location as size] */
 | 
				
			||||||
  OP_GET,          /* get  : dest = ptr : dest = memory[ptr] */
 | 
					  OP_GET,           /* get  : dest = ptr : dest = memory[ptr] */
 | 
				
			||||||
  OP_PUT,          /* put  : ptr = src1  : memory[ptr] = src */
 | 
					  OP_PUT,           /* put  : ptr = src1  : memory[ptr] = src */
 | 
				
			||||||
  OP_OFFSET,       /* offs : dest = ptr + src1 : dest = p + o */
 | 
					  OP_OFFSET,        /* offs : dest = ptr + src1 : dest = p + o */
 | 
				
			||||||
  OP_SYSCALL,      /* sysc :  */
 | 
					  OP_SYSCALL,       /* sysc :  */
 | 
				
			||||||
  OP_ADD_INT,      /* addi : dest = src1 + src2  */
 | 
					  OP_ADD_INT,       /* addi : dest = src1 + src2  */
 | 
				
			||||||
  OP_SUB_INT,      /* subi : dest = src1 - src2  */
 | 
					  OP_SUB_INT,       /* subi : dest = src1 - src2  */
 | 
				
			||||||
  OP_MUL_INT,      /* muli : dest = src1 * src2  */
 | 
					  OP_MUL_INT,       /* muli : dest = src1 * src2  */
 | 
				
			||||||
  OP_DIV_INT,      /* divi : dest = src1 / src2  */
 | 
					  OP_DIV_INT,       /* divi : dest = src1 / src2  */
 | 
				
			||||||
  OP_ADD_UINT,     /* addu : dest = src1 + src2  */
 | 
					  OP_ADD_UINT,      /* addu : dest = src1 + src2  */
 | 
				
			||||||
  OP_SUB_UINT,     /* subu : dest = src1 - src2  */
 | 
					  OP_SUB_UINT,      /* subu : dest = src1 - src2  */
 | 
				
			||||||
  OP_MUL_UINT,     /* mulu : dest = src1 * src2  */
 | 
					  OP_MUL_UINT,      /* mulu : dest = src1 * src2  */
 | 
				
			||||||
  OP_DIV_UINT,     /* divu : dest = src1 / src2  */
 | 
					  OP_DIV_UINT,      /* divu : dest = src1 / src2  */
 | 
				
			||||||
  OP_ADD_REAL,     /* addr : dest = src1 + src2  */
 | 
					  OP_ADD_REAL,      /* addr : dest = src1 + src2  */
 | 
				
			||||||
  OP_SUB_REAL,     /* subr : dest = src1 - src2  */
 | 
					  OP_SUB_REAL,      /* subr : dest = src1 - src2  */
 | 
				
			||||||
  OP_MUL_REAL,     /* mulr : dest = src1 * src2  */
 | 
					  OP_MUL_REAL,      /* mulr : dest = src1 * src2  */
 | 
				
			||||||
  OP_DIV_REAL,     /* divr : dest = src1 / src2  */
 | 
					  OP_DIV_REAL,      /* divr : dest = src1 / src2  */
 | 
				
			||||||
  OP_INT_TO_REAL,  /* itor : dest = src1 as real  */
 | 
					  OP_INT_TO_REAL,   /* itor : dest = src1 as real  */
 | 
				
			||||||
  OP_UINT_TO_REAL, /* utor : dest = src1 as real  */
 | 
					  OP_UINT_TO_REAL,  /* utor : dest = src1 as real  */
 | 
				
			||||||
  OP_REAL_TO_INT,  /* rtoi : dest = src1 as int  */
 | 
					  OP_REAL_TO_INT,   /* rtoi : dest = src1 as int  */
 | 
				
			||||||
  OP_REAL_TO_UINT, /* rtou : dest = src1 as uint  */
 | 
					  OP_REAL_TO_UINT,  /* rtou : dest = src1 as uint  */
 | 
				
			||||||
  OP_JEQ_INT,  /* jeqi : jump to address dest if src1 as int == src2 as int */
 | 
					  OP_JEQ_INT,       /* jeqi : jump to address dest if src1 as int == src2 as int */
 | 
				
			||||||
  OP_JGT_INT,  /* jgti : jump to address dest if src1 as int > src2 as int*/
 | 
					  OP_JGT_INT,       /* jgti : jump to address dest if src1 as int > src2 as int*/
 | 
				
			||||||
  OP_JLT_INT,  /* jlti : jump to address dest if src1 as int < src2 as int */
 | 
					  OP_JLT_INT,       /* jlti : jump to address dest if src1 as int < src2 as int */
 | 
				
			||||||
  OP_JLE_INT,  /* jlei : jump to address dest if src1 as int <= src2 as int */
 | 
					  OP_JLE_INT,       /* jlei : jump to address dest if src1 as int <= src2 as int */
 | 
				
			||||||
  OP_JGE_INT,  /* jgei : jump to address dest if src1 as int >= src2 as int*/
 | 
					  OP_JGE_INT,       /* jgei : jump to address dest if src1 as int >= src2 as int*/
 | 
				
			||||||
  OP_JEQ_UINT, /* jequ : jump to address dest if src1 as int == src2 as uint */
 | 
					  OP_JEQ_UINT,      /* jequ : jump to address dest if src1 as int == src2 as uint */
 | 
				
			||||||
  OP_JGT_UINT, /* jgtu : jump to address dest if src1 as int > src2 as uint*/
 | 
					  OP_JGT_UINT,      /* jgtu : jump to address dest if src1 as int > src2 as uint*/
 | 
				
			||||||
  OP_JLT_UINT, /* jltu : jump to address dest if src1 as int < src2 as uint */
 | 
					  OP_JLT_UINT,      /* jltu : jump to address dest if src1 as int < src2 as uint */
 | 
				
			||||||
  OP_JLE_UINT, /* jleu : jump to address dest if src1 as int <= src2 as uint */
 | 
					  OP_JLE_UINT,      /* jleu : jump to address dest if src1 as int <= src2 as uint */
 | 
				
			||||||
  OP_JGE_UINT, /* jgeu : jump to address dest if src1 as int >= src2 as uint*/
 | 
					  OP_JGE_UINT,      /* jgeu : jump to address dest if src1 as int >= src2 as uint*/
 | 
				
			||||||
  OP_JEQ_REAL, /* jeqr : jump to address dest if src1 as real == src2 as real */
 | 
					  OP_JEQ_REAL,      /* jeqr : jump to address dest if src1 as real == src2 as real */
 | 
				
			||||||
  OP_JGE_REAL, /* jgtr : jump to address dest if src1 as real >= src2 as real */
 | 
					  OP_JGE_REAL,      /* jgtr : jump to address dest if src1 as real >= src2 as real */
 | 
				
			||||||
  OP_JGT_REAL, /* jltr : jump to address dest if src1 as real > src2 as real */
 | 
					  OP_JGT_REAL,      /* jltr : jump to address dest if src1 as real > src2 as real */
 | 
				
			||||||
  OP_JLT_REAL, /* jler : jump to address dest if src1 as real < src2 as real */
 | 
					  OP_JLT_REAL,      /* jler : jump to address dest if src1 as real < src2 as real */
 | 
				
			||||||
  OP_JLE_REAL, /* jger : jump to address dest if src1 as real <= src2 as real */
 | 
					  OP_JLE_REAL,      /* jger : jump to address dest if src1 as real <= src2 as real */
 | 
				
			||||||
  OP_INT_TO_STRING,  /* itos : dest = src1 as str */
 | 
					  OP_INT_TO_STRING, /* itos : dest = src1 as str */
 | 
				
			||||||
  OP_UINT_TO_STRING, /* utos : dest = src1 as str */
 | 
					  OP_UINT_TO_STRING,/* utos : dest = src1 as str */
 | 
				
			||||||
  OP_REAL_TO_STRING, /* rtos : dest = src1 as str */
 | 
					  OP_REAL_TO_STRING,/* rtos : dest = src1 as str */
 | 
				
			||||||
  OP_CMP_STRING,     /* cmps : dest = (str == src2) as bool */
 | 
					  OP_CMP_STRING,    /* cmps : dest = (str == src2) as bool */
 | 
				
			||||||
  OP_STRING_TO_INT,  /* stoi : dest = src1 as int */
 | 
					  OP_STRING_TO_INT, /* stoi : dest = src1 as int */
 | 
				
			||||||
  OP_STRING_TO_UINT, /* stou : dest = src1 as uint */
 | 
					  OP_STRING_TO_UINT,/* stou : dest = src1 as uint */
 | 
				
			||||||
  OP_STRING_TO_REAL, /* stor : dest = src1 as real */
 | 
					  OP_STRING_TO_REAL,/* stor : dest = src1 as real */
 | 
				
			||||||
  /* to remove (replace with device), just for testing for now */
 | 
					  /* to remove (replace with device), just for testing for now */
 | 
				
			||||||
  OP_DBG_PRINT_STRING,
 | 
					  OP_DBG_PRINT_STRING,/* puts : write src1 as str to stdout */
 | 
				
			||||||
  OP_DBG_READ_STRING,
 | 
					  OP_DBG_READ_STRING, /* gets : read to dest as str from stdin */
 | 
				
			||||||
} Opcode;
 | 
					} Opcode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* defines a uint32 opcode */
 | 
					/* defines a uint32 opcode */
 | 
				
			||||||
| 
						 | 
					@ -76,7 +77,7 @@ typedef enum {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef union value_u {
 | 
					typedef union value_u {
 | 
				
			||||||
  int32_t i;  /* Integers */
 | 
					  int32_t i;  /* Integers */
 | 
				
			||||||
  float f;    /* Float */
 | 
					  fixed_t f;  /* Fixed point */
 | 
				
			||||||
  uint32_t u; /* Unsigned integers, also used for pointer address */
 | 
					  uint32_t u; /* Unsigned integers, also used for pointer address */
 | 
				
			||||||
  char c[4];  /* 4 Byte char array for string packing */
 | 
					  char c[4];  /* 4 Byte char array for string packing */
 | 
				
			||||||
} Value;
 | 
					} Value;
 | 
				
			||||||
| 
						 | 
					@ -123,7 +124,7 @@ typedef struct device_s {
 | 
				
			||||||
  uint32_t flags;                    /* permissions, status, etc. */
 | 
					  uint32_t flags;                    /* permissions, status, etc. */
 | 
				
			||||||
} Device;
 | 
					} Device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MEMORY_SIZE (640 * 480 + 65536)
 | 
					#define MEMORY_SIZE ((640 * 480) + 65536)
 | 
				
			||||||
#define CODE_SIZE 8192
 | 
					#define CODE_SIZE 8192
 | 
				
			||||||
#define FRAMES_SIZE 128
 | 
					#define FRAMES_SIZE 128
 | 
				
			||||||
#define STACK_SIZE 256
 | 
					#define STACK_SIZE 256
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										277
									
								
								src/vm.c
								
								
								
								
							
							
						
						
									
										277
									
								
								src/vm.c
								
								
								
								
							| 
						 | 
					@ -1,6 +1,8 @@
 | 
				
			||||||
#include "vm.h"
 | 
					#include "vm.h"
 | 
				
			||||||
#include "device.h"
 | 
					#include "device.h"
 | 
				
			||||||
#include <string.h>
 | 
					#include "fixed.h"
 | 
				
			||||||
 | 
					#include "opcodes.h"
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* no inline fn in ANSI C :( */
 | 
					/* no inline fn in ANSI C :( */
 | 
				
			||||||
#define COMPARE_AND_JUMP(type, accessor, op)                                   \
 | 
					#define COMPARE_AND_JUMP(type, accessor, op)                                   \
 | 
				
			||||||
| 
						 | 
					@ -12,17 +14,6 @@
 | 
				
			||||||
    return true;                                                               \
 | 
					    return true;                                                               \
 | 
				
			||||||
  } while (0)
 | 
					  } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MATH_OP(accessor, op)                                                  \
 | 
					 | 
				
			||||||
  do {                                                                         \
 | 
					 | 
				
			||||||
    vm->frames[vm->fp].registers[dest].accessor =                              \
 | 
					 | 
				
			||||||
        vm->frames[vm->fp]                                                     \
 | 
					 | 
				
			||||||
            .registers[src1]                                                   \
 | 
					 | 
				
			||||||
            .accessor op vm->frames[vm->fp]                                    \
 | 
					 | 
				
			||||||
            .registers[src2]                                                   \
 | 
					 | 
				
			||||||
            .accessor;                                                         \
 | 
					 | 
				
			||||||
    return true;                                                               \
 | 
					 | 
				
			||||||
  } while (0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Embeds a string into the VM
 | 
					 * Embeds a string into the VM
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -49,11 +40,17 @@ uint32_t str_alloc(VM *vm, const char *str, uint32_t length) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  vm->memory[str_addr].u = length;
 | 
					  vm->memory[str_addr].u = length;
 | 
				
			||||||
  vm->frames[vm->fp].allocated.end = vm->mp;
 | 
					  vm->frames[vm->fp].allocated.end = vm->mp;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  return str_addr;
 | 
					  return str_addr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t real_alloc(VM *vm, float v) {
 | 
					uint32_t float_as_real_alloc(VM *vm, float v) {
 | 
				
			||||||
 | 
					  uint32_t addr = vm->mp;
 | 
				
			||||||
 | 
					  vm->memory[vm->mp++].f = float_to_fixed(v);
 | 
				
			||||||
 | 
					  vm->frames[vm->fp].allocated.end++;
 | 
				
			||||||
 | 
					  return addr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t real_alloc(VM *vm, fixed_t v) {
 | 
				
			||||||
  uint32_t addr = vm->mp;
 | 
					  uint32_t addr = vm->mp;
 | 
				
			||||||
  vm->memory[vm->mp++].f = v;
 | 
					  vm->memory[vm->mp++].f = v;
 | 
				
			||||||
  vm->frames[vm->fp].allocated.end++;
 | 
					  vm->frames[vm->fp].allocated.end++;
 | 
				
			||||||
| 
						 | 
					@ -74,6 +71,94 @@ uint32_t int_alloc(VM *vm, int32_t v) {
 | 
				
			||||||
  return addr;
 | 
					  return addr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_LEN_INT32 12  /* -2147483648 plus null terminator */
 | 
				
			||||||
 | 
					#define MAX_LEN_UINT32 11 /* 4294967295 plus null terminator */
 | 
				
			||||||
 | 
					#define MAX_LEN_FIXED 20  /* Enough for fixed-point representation */
 | 
				
			||||||
 | 
					const char radix_set[11] = "0123456789";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Convert int32 to string */
 | 
				
			||||||
 | 
					uint32_t int_to_string(VM *vm, int32_t v) {
 | 
				
			||||||
 | 
					  char buffer[MAX_LEN_INT32] = {0};
 | 
				
			||||||
 | 
					  int32_t n = v;
 | 
				
			||||||
 | 
					  bool neg = n < 0;
 | 
				
			||||||
 | 
					  if (neg)
 | 
				
			||||||
 | 
					    n = -n;
 | 
				
			||||||
 | 
					  int i = MAX_LEN_INT32;
 | 
				
			||||||
 | 
					  do {
 | 
				
			||||||
 | 
					    buffer[--i] = radix_set[n % 10];
 | 
				
			||||||
 | 
					    n /= 10;
 | 
				
			||||||
 | 
					  } while (n > 0);
 | 
				
			||||||
 | 
					  if (neg)
 | 
				
			||||||
 | 
					    buffer[--i] = '-';
 | 
				
			||||||
 | 
					  /* Ensure at least one digit is written for 0 */
 | 
				
			||||||
 | 
					  if (v == 0)
 | 
				
			||||||
 | 
					    buffer[--i] = '0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint32_t len = MAX_LEN_INT32 - i;
 | 
				
			||||||
 | 
					  return str_alloc(vm, buffer + i, len);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Convert uint32 to string */
 | 
				
			||||||
 | 
					uint32_t nat_to_string(VM *vm, uint32_t v) {
 | 
				
			||||||
 | 
					  char buffer[MAX_LEN_INT32] = {0};
 | 
				
			||||||
 | 
					  uint32_t n = v;
 | 
				
			||||||
 | 
					  int i = MAX_LEN_INT32;
 | 
				
			||||||
 | 
					  do {
 | 
				
			||||||
 | 
					    buffer[--i] = radix_set[n % 10];
 | 
				
			||||||
 | 
					    n /= 10;
 | 
				
			||||||
 | 
					  } while (n > 0);
 | 
				
			||||||
 | 
					  /* Ensure at least one digit is written for 0 */
 | 
				
			||||||
 | 
					  if (v == 0)
 | 
				
			||||||
 | 
					    buffer[--i] = '0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint32_t len = MAX_LEN_INT32 - i;
 | 
				
			||||||
 | 
					  return str_alloc(vm, buffer + i, len);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Convert fixed-point to string */
 | 
				
			||||||
 | 
					uint32_t real_to_string(VM *vm, fixed_t q) {
 | 
				
			||||||
 | 
					  char buffer[MAX_LEN_FIXED] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Extract integer part (top 16 bits) */
 | 
				
			||||||
 | 
					  int32_t int_part = q >> 16;
 | 
				
			||||||
 | 
					  /* Extract fractional part (bottom 16 bits) */
 | 
				
			||||||
 | 
					  int32_t frac_part = q & 0xFFFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int32_t n = frac_part;
 | 
				
			||||||
 | 
					  bool neg = n < 0;
 | 
				
			||||||
 | 
					  if (neg)
 | 
				
			||||||
 | 
					    n = -n;
 | 
				
			||||||
 | 
					  int i = MAX_LEN_FIXED;
 | 
				
			||||||
 | 
					  do {
 | 
				
			||||||
 | 
					    buffer[--i] = radix_set[n % 10];
 | 
				
			||||||
 | 
					    n /= 10;
 | 
				
			||||||
 | 
					  } while (n > 0);
 | 
				
			||||||
 | 
					  if (neg)
 | 
				
			||||||
 | 
					    buffer[--i] = '-';
 | 
				
			||||||
 | 
					  /* Ensure at least one digit is written for 0 */
 | 
				
			||||||
 | 
					  if (frac_part == 0)
 | 
				
			||||||
 | 
					    buffer[--i] = '0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Convert integer part to string (reverse order) */
 | 
				
			||||||
 | 
					  do {
 | 
				
			||||||
 | 
					    buffer[--i] = radix_set[int_part % 10];
 | 
				
			||||||
 | 
					    int_part /= 10;
 | 
				
			||||||
 | 
					  } while (int_part > 0);
 | 
				
			||||||
 | 
					  /* Ensure at least one digit is written for 0 */
 | 
				
			||||||
 | 
					  if (int_part == 0)
 | 
				
			||||||
 | 
					    buffer[--i] = '0';    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Null-terminate */
 | 
				
			||||||
 | 
					  buffer[i] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int32_t len = (MAX_LEN_INT32 - i);
 | 
				
			||||||
 | 
					  printf("i=%d, len=%d", i, len);
 | 
				
			||||||
 | 
					  return str_alloc(vm, buffer + i, len);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Step to the next opcode in the vm.
 | 
					 * Step to the next opcode in the vm.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -108,7 +193,9 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_LOAD: {
 | 
					  case OP_LOAD: {
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest].u = vm->code[vm->pc++].u;
 | 
					    uint32_t ptr = vm->code[vm->pc++].u;
 | 
				
			||||||
 | 
					    Value v = vm->memory[ptr];
 | 
				
			||||||
 | 
					    vm->frames[vm->fp].registers[dest] = v;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_STORE: {
 | 
					  case OP_STORE: {
 | 
				
			||||||
| 
						 | 
					@ -134,11 +221,13 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_PUSH: {
 | 
					  case OP_PUSH: {
 | 
				
			||||||
    vm->stack[++vm->sp] = vm->frames[vm->fp].registers[dest];
 | 
					    Value v = vm->frames[vm->fp].registers[dest];
 | 
				
			||||||
 | 
					    vm->stack[++vm->sp] = v;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_POP: {
 | 
					  case OP_POP: {
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] = vm->stack[vm->sp--];
 | 
					    Value v = vm->stack[vm->sp--];
 | 
				
			||||||
 | 
					    vm->frames[vm->fp].registers[dest] = v;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_MEM_ALLOC: {
 | 
					  case OP_MEM_ALLOC: {
 | 
				
			||||||
| 
						 | 
					@ -317,48 +406,98 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_ADD_INT:
 | 
					  case OP_ADD_INT: {
 | 
				
			||||||
    MATH_OP(i, +);
 | 
					    vm->frames[vm->fp].registers[dest].i =
 | 
				
			||||||
  case OP_SUB_INT:
 | 
					        vm->frames[vm->fp].registers[src1].i +
 | 
				
			||||||
    MATH_OP(i, -);
 | 
					        vm->frames[vm->fp].registers[src2].i;
 | 
				
			||||||
  case OP_MUL_INT:
 | 
					    return true;
 | 
				
			||||||
    MATH_OP(i, *);
 | 
					  }
 | 
				
			||||||
  case OP_DIV_INT:
 | 
					  case OP_SUB_INT:{
 | 
				
			||||||
    MATH_OP(i, /);
 | 
					    vm->frames[vm->fp].registers[dest].i =
 | 
				
			||||||
  case OP_ADD_UINT:
 | 
					        vm->frames[vm->fp].registers[src1].i -
 | 
				
			||||||
    MATH_OP(u, +);
 | 
					        vm->frames[vm->fp].registers[src2].i;
 | 
				
			||||||
  case OP_SUB_UINT:
 | 
					    return true;
 | 
				
			||||||
    MATH_OP(u, -);
 | 
					  }
 | 
				
			||||||
  case OP_MUL_UINT:
 | 
					  case OP_MUL_INT:{
 | 
				
			||||||
    MATH_OP(u, *);
 | 
					    vm->frames[vm->fp].registers[dest].i =
 | 
				
			||||||
  case OP_DIV_UINT:
 | 
					        vm->frames[vm->fp].registers[src1].i *
 | 
				
			||||||
    MATH_OP(u, /);
 | 
					        vm->frames[vm->fp].registers[src2].i;
 | 
				
			||||||
  case OP_ADD_REAL:
 | 
					    return true;
 | 
				
			||||||
    MATH_OP(f, +);
 | 
					  }
 | 
				
			||||||
  case OP_SUB_REAL:
 | 
					  case OP_DIV_INT:{
 | 
				
			||||||
    MATH_OP(f, -);
 | 
					    vm->frames[vm->fp].registers[dest].i =
 | 
				
			||||||
  case OP_MUL_REAL:
 | 
					        vm->frames[vm->fp].registers[src1].i /
 | 
				
			||||||
    MATH_OP(f, *);
 | 
					        vm->frames[vm->fp].registers[src2].i;
 | 
				
			||||||
  case OP_DIV_REAL:
 | 
					    return true;
 | 
				
			||||||
    MATH_OP(f, /);
 | 
					  }
 | 
				
			||||||
 | 
					  case OP_ADD_UINT:{
 | 
				
			||||||
 | 
					    vm->frames[vm->fp].registers[dest].u =
 | 
				
			||||||
 | 
					        vm->frames[vm->fp].registers[src1].u +
 | 
				
			||||||
 | 
					        vm->frames[vm->fp].registers[src2].u;
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  case OP_SUB_UINT:{
 | 
				
			||||||
 | 
					    vm->frames[vm->fp].registers[dest].u =
 | 
				
			||||||
 | 
					        vm->frames[vm->fp].registers[src1].u -
 | 
				
			||||||
 | 
					        vm->frames[vm->fp].registers[src2].u;
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  case OP_MUL_UINT:{
 | 
				
			||||||
 | 
					    vm->frames[vm->fp].registers[dest].u =
 | 
				
			||||||
 | 
					        vm->frames[vm->fp].registers[src1].u *
 | 
				
			||||||
 | 
					        vm->frames[vm->fp].registers[src2].u;
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  case OP_DIV_UINT:{
 | 
				
			||||||
 | 
					    vm->frames[vm->fp].registers[dest].u =
 | 
				
			||||||
 | 
					        vm->frames[vm->fp].registers[src1].u /
 | 
				
			||||||
 | 
					        vm->frames[vm->fp].registers[src2].u;
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  case OP_ADD_REAL:{
 | 
				
			||||||
 | 
					    vm->frames[vm->fp].registers[dest].f =
 | 
				
			||||||
 | 
					        fixed_add(vm->frames[vm->fp].registers[src1].f,
 | 
				
			||||||
 | 
					                  vm->frames[vm->fp].registers[src2].f);
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  case OP_SUB_REAL:{
 | 
				
			||||||
 | 
					    vm->frames[vm->fp].registers[dest].f =
 | 
				
			||||||
 | 
					        fixed_sub(vm->frames[vm->fp].registers[src1].f,
 | 
				
			||||||
 | 
					                  vm->frames[vm->fp].registers[src2].f);
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  case OP_MUL_REAL: {
 | 
				
			||||||
 | 
					    vm->frames[vm->fp].registers[dest].f =
 | 
				
			||||||
 | 
					        fixed_mul(vm->frames[vm->fp].registers[src1].f,
 | 
				
			||||||
 | 
					                  vm->frames[vm->fp].registers[src2].f);
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  case OP_DIV_REAL: {
 | 
				
			||||||
 | 
					    vm->frames[vm->fp].registers[dest].f =
 | 
				
			||||||
 | 
					        fixed_div(vm->frames[vm->fp].registers[src1].f,
 | 
				
			||||||
 | 
					                  vm->frames[vm->fp].registers[src2].f);
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  case OP_REAL_TO_INT: {
 | 
					  case OP_REAL_TO_INT: {
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest].i =
 | 
					    vm->frames[vm->fp].registers[dest].i =
 | 
				
			||||||
        (int32_t)(vm->frames[vm->fp].registers[src1].f);
 | 
					        fixed_to_int(vm->frames[vm->fp].registers[src1].f);
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_INT_TO_REAL: {
 | 
					  case OP_INT_TO_REAL: {
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest].f =
 | 
					    vm->frames[vm->fp].registers[dest].f =
 | 
				
			||||||
        (float)(vm->frames[vm->fp].registers[src1].i);
 | 
					        int_to_fixed(vm->frames[vm->fp].registers[src1].i);
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_REAL_TO_UINT: {
 | 
					  case OP_REAL_TO_UINT: {
 | 
				
			||||||
 | 
					    fixed_t f = vm->frames[vm->fp].registers[src1].f;
 | 
				
			||||||
 | 
					    int32_t i = fixed_to_int(f);
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest].u =
 | 
					    vm->frames[vm->fp].registers[dest].u =
 | 
				
			||||||
        (uint32_t)(vm->frames[vm->fp].registers[src1].f);
 | 
					        (uint32_t)i;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_UINT_TO_REAL: {
 | 
					  case OP_UINT_TO_REAL: {
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest].f =
 | 
					    vm->frames[vm->fp].registers[dest].f =
 | 
				
			||||||
        (float)(vm->frames[vm->fp].registers[src1].u);
 | 
					        int_to_fixed(vm->frames[vm->fp].registers[src1].u);
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_REG_SWAP: {
 | 
					  case OP_REG_SWAP: {
 | 
				
			||||||
| 
						 | 
					@ -420,38 +559,48 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    COMPARE_AND_JUMP(int32_t, i, ==);
 | 
					    COMPARE_AND_JUMP(int32_t, i, ==);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_JGT_REAL: {
 | 
					  case OP_JGT_REAL: {
 | 
				
			||||||
    COMPARE_AND_JUMP(float, u, >);
 | 
					    fixed_t value = vm->frames[vm->fp].registers[src1].f;
 | 
				
			||||||
 | 
					    fixed_t value2 = vm->frames[vm->fp].registers[src2].f;
 | 
				
			||||||
 | 
					    vm->pc =
 | 
				
			||||||
 | 
					        fixed_gt(value, value2) ? vm->frames[vm->fp].registers[dest].u : vm->pc;
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_JLT_REAL: {
 | 
					  case OP_JLT_REAL: {
 | 
				
			||||||
    COMPARE_AND_JUMP(float, u, <);
 | 
					    fixed_t value = vm->frames[vm->fp].registers[src1].f;
 | 
				
			||||||
 | 
					    fixed_t value2 = vm->frames[vm->fp].registers[src2].f;
 | 
				
			||||||
 | 
					    vm->pc =
 | 
				
			||||||
 | 
					        fixed_lt(value, value2) ? vm->frames[vm->fp].registers[dest].u : vm->pc;
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_JGE_REAL: {
 | 
					  case OP_JGE_REAL: {
 | 
				
			||||||
    COMPARE_AND_JUMP(float, u, >=);
 | 
					    fixed_t value = vm->frames[vm->fp].registers[src1].f;
 | 
				
			||||||
 | 
					    fixed_t value2 = vm->frames[vm->fp].registers[src2].f;
 | 
				
			||||||
 | 
					    vm->pc =
 | 
				
			||||||
 | 
					        fixed_ge(value, value2) ? vm->frames[vm->fp].registers[dest].u : vm->pc;
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_JLE_REAL: {
 | 
					  case OP_JLE_REAL: {
 | 
				
			||||||
    COMPARE_AND_JUMP(float, u, <=);
 | 
					    fixed_t value = vm->frames[vm->fp].registers[src1].f;
 | 
				
			||||||
 | 
					    fixed_t value2 = vm->frames[vm->fp].registers[src2].f;
 | 
				
			||||||
 | 
					    vm->pc =
 | 
				
			||||||
 | 
					        fixed_le(value, value2) ? vm->frames[vm->fp].registers[dest].u : vm->pc;
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_INT_TO_STRING: {
 | 
					  case OP_INT_TO_STRING: {
 | 
				
			||||||
    int32_t a = (int32_t)vm->frames[vm->fp].registers[src1].i; /* get value */
 | 
					    int32_t a = vm->frames[vm->fp].registers[src1].i; 
 | 
				
			||||||
    char buffer[32];
 | 
					    uint32_t ptr = int_to_string(vm, a);
 | 
				
			||||||
    int len = sprintf(buffer, "%d", a);
 | 
					 | 
				
			||||||
    uint32_t ptr = str_alloc(vm, buffer, len); /* copy buffer to dest */
 | 
					 | 
				
			||||||
    vm->frames[vm->fp].registers[dest].u = ptr;
 | 
					    vm->frames[vm->fp].registers[dest].u = ptr;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_UINT_TO_STRING: {
 | 
					  case OP_UINT_TO_STRING: {
 | 
				
			||||||
    uint32_t a = (uint32_t)vm->frames[vm->fp].registers[src1].u; /* get value */
 | 
					    uint32_t a = vm->frames[vm->fp].registers[src1].u;
 | 
				
			||||||
    char buffer[32];
 | 
					    uint32_t ptr = nat_to_string(vm, a);
 | 
				
			||||||
    int len = sprintf(buffer, "%d", a);
 | 
					 | 
				
			||||||
    uint32_t ptr = str_alloc(vm, buffer, len); /* copy buffer to dest */
 | 
					 | 
				
			||||||
    vm->frames[vm->fp].registers[dest].u = ptr;
 | 
					    vm->frames[vm->fp].registers[dest].u = ptr;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_REAL_TO_STRING: {
 | 
					  case OP_REAL_TO_STRING: {
 | 
				
			||||||
    float a = (float)vm->frames[vm->fp].registers[src1].f; /* get value */
 | 
					    fixed_t a = vm->frames[vm->fp].registers[src1].f; 
 | 
				
			||||||
    char buffer[32];
 | 
					    uint32_t ptr = real_to_string(vm, a);
 | 
				
			||||||
    int len = sprintf(buffer, "%f", a);
 | 
					 | 
				
			||||||
    uint32_t ptr = str_alloc(vm, buffer, len); /* copy buffer to dest */
 | 
					 | 
				
			||||||
    vm->frames[vm->fp].registers[dest].u = ptr;
 | 
					    vm->frames[vm->fp].registers[dest].u = ptr;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -484,7 +633,7 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_DBG_PRINT_STRING: {
 | 
					  case OP_DBG_PRINT_STRING: {
 | 
				
			||||||
    uint32_t ptr = (uint32_t)vm->frames[vm->fp].registers[src1].u;
 | 
					    uint32_t ptr = vm->frames[vm->fp].registers[src1].u;
 | 
				
			||||||
    uint32_t length = vm->memory[ptr].u;
 | 
					    uint32_t length = vm->memory[ptr].u;
 | 
				
			||||||
    uint32_t str_src = ptr + 1;
 | 
					    uint32_t str_src = ptr + 1;
 | 
				
			||||||
    uint32_t i;
 | 
					    uint32_t i;
 | 
				
			||||||
| 
						 | 
					@ -498,8 +647,8 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_CMP_STRING: {
 | 
					  case OP_CMP_STRING: {
 | 
				
			||||||
    uint32_t addr1 = (uint32_t)vm->frames[vm->fp].registers[src1].u;
 | 
					    uint32_t addr1 = vm->frames[vm->fp].registers[src1].u;
 | 
				
			||||||
    uint32_t addr2 = (uint32_t)vm->frames[vm->fp].registers[src2].u;
 | 
					    uint32_t addr2 = vm->frames[vm->fp].registers[src2].u;
 | 
				
			||||||
    uint32_t length1 = vm->memory[addr1 - 1].u;
 | 
					    uint32_t length1 = vm->memory[addr1 - 1].u;
 | 
				
			||||||
    uint32_t length2 = vm->memory[addr2 - 1].u;
 | 
					    uint32_t length2 = vm->memory[addr2 - 1].u;
 | 
				
			||||||
    uint32_t equal =
 | 
					    uint32_t equal =
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/vm.h
								
								
								
								
							
							
						
						
									
										3
									
								
								src/vm.h
								
								
								
								
							| 
						 | 
					@ -6,7 +6,8 @@
 | 
				
			||||||
VM* init_vm();
 | 
					VM* init_vm();
 | 
				
			||||||
bool step_vm(VM *vm);
 | 
					bool step_vm(VM *vm);
 | 
				
			||||||
uint32_t str_alloc(VM *vm, const char *str, uint32_t length);
 | 
					uint32_t str_alloc(VM *vm, const char *str, uint32_t length);
 | 
				
			||||||
uint32_t real_alloc(VM *vm, float v);
 | 
					uint32_t float_as_real_alloc(VM *vm, float v);
 | 
				
			||||||
 | 
					uint32_t real_alloc(VM *vm, fixed_t v);
 | 
				
			||||||
uint32_t nat_alloc(VM *vm, uint32_t v);
 | 
					uint32_t nat_alloc(VM *vm, uint32_t v);
 | 
				
			||||||
uint32_t int_alloc(VM *vm, int32_t v);
 | 
					uint32_t int_alloc(VM *vm, int32_t v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue