Compare commits
	
		
			2 Commits
		
	
	
		
			b8832a7116
			...
			2d72240652
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								
								 | 
						2d72240652 | |
| 
							
							
								
								 | 
						cf0318e96f | 
							
								
								
									
										110
									
								
								src/opcodes.h
								
								
								
								
							
							
						
						
									
										110
									
								
								src/opcodes.h
								
								
								
								
							| 
						 | 
					@ -4,55 +4,61 @@
 | 
				
			||||||
#include "common.h"
 | 
					#include "common.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_CALL,     /* call : creates a new frame */
 | 
					  OP_JMPF,           /* jmpf : jump to address dest if flag is ne 0 */
 | 
				
			||||||
  OP_RETURN,   /* retn : returns from a frame to the parent frame */
 | 
					  OP_CALL,           /* call : creates a new frame */
 | 
				
			||||||
  OP_LOAD,     /* load : dest = &[next memory location] */
 | 
					  OP_RETURN,         /* retn : returns from a frame to the parent frame */
 | 
				
			||||||
  OP_LOAD_IMM, /* load : dest = &[next memory location] */
 | 
					  OP_LOAD,           /* load : dest = &[next memory location] */
 | 
				
			||||||
  OP_STORE,    /* stor : next memory location = src1 as float */
 | 
					  OP_LOAD_IMM,       /* load : dest = &[next memory location] */
 | 
				
			||||||
  OP_PUSH, /* push : push str ref from register onto the stack and copy str  */
 | 
					  OP_STORE,          /* stor : next memory location = src1 as float */
 | 
				
			||||||
  OP_POP,  /* pop  : pop int from stack onto the register */
 | 
					  OP_PUSH,           /* push : push str ref from register onto the stack and copy str  */
 | 
				
			||||||
  OP_REG_MOV,      /* rmov : dest = src1	   */
 | 
					  OP_POP,            /* pop  : pop int from stack onto the register */
 | 
				
			||||||
  OP_SYSCALL,      /* sysc :  */
 | 
					  OP_REG_MOV,        /* rmov : dest = src1	   */
 | 
				
			||||||
  OP_ADD_INT,      /* addi : dest = src1 + src2  */
 | 
					  OP_SYSCALL,        /* sysc :  */
 | 
				
			||||||
  OP_SUB_INT,      /* subi : dest = src1 - src2  */
 | 
					  OP_ADD_INT,        /* addi : dest = src1 + src2  */
 | 
				
			||||||
  OP_MUL_INT,      /* muli : dest = src1 * src2  */
 | 
					  OP_SUB_INT,        /* subi : dest = src1 - src2  */
 | 
				
			||||||
  OP_DIV_INT,      /* divi : dest = src1 / src2  */
 | 
					  OP_MUL_INT,        /* muli : dest = src1 * src2  */
 | 
				
			||||||
  OP_ADD_UINT,     /* addu : dest = src1 + src2  */
 | 
					  OP_DIV_INT,        /* divi : dest = src1 / src2  */
 | 
				
			||||||
  OP_SUB_UINT,     /* subu : dest = src1 - src2  */
 | 
					  OP_ADD_UINT,       /* addu : dest = src1 + src2  */
 | 
				
			||||||
  OP_MUL_UINT,     /* mulu : dest = src1 * src2  */
 | 
					  OP_SUB_UINT,       /* subu : dest = src1 - src2  */
 | 
				
			||||||
  OP_DIV_UINT,     /* divu : dest = src1 / src2  */
 | 
					  OP_MUL_UINT,       /* mulu : dest = src1 * src2  */
 | 
				
			||||||
  OP_ADD_REAL,     /* addr : dest = src1 + src2  */
 | 
					  OP_DIV_UINT,       /* divu : dest = src1 / src2  */
 | 
				
			||||||
  OP_SUB_REAL,     /* subr : dest = src1 - src2  */
 | 
					  OP_ADD_REAL,       /* addr : dest = src1 + src2  */
 | 
				
			||||||
  OP_MUL_REAL,     /* mulr : dest = src1 * src2  */
 | 
					  OP_SUB_REAL,       /* subr : dest = src1 - src2  */
 | 
				
			||||||
  OP_DIV_REAL,     /* divr : dest = src1 / src2  */
 | 
					  OP_MUL_REAL,       /* mulr : dest = src1 * src2  */
 | 
				
			||||||
  OP_INT_TO_REAL,  /* itor : dest = src1 as real  */
 | 
					  OP_DIV_REAL,       /* divr : dest = src1 / src2  */
 | 
				
			||||||
  OP_UINT_TO_REAL, /* utor : dest = src1 as real  */
 | 
					  OP_INT_TO_REAL,    /* itor : dest = src1 as real  */
 | 
				
			||||||
  OP_REAL_TO_INT,  /* rtoi : dest = src1 as int  */
 | 
					  OP_UINT_TO_REAL,   /* utor : dest = src1 as real  */
 | 
				
			||||||
  OP_REAL_TO_UINT, /* rtou : dest = src1 as uint  */
 | 
					  OP_REAL_TO_INT,    /* rtoi : dest = src1 as int  */
 | 
				
			||||||
  OP_JEQ_INT,  /* jeqi : jump to address dest if src1 as int == src2 as int */
 | 
					  OP_REAL_TO_UINT,   /* rtou : dest = src1 as uint  */
 | 
				
			||||||
  OP_JGT_INT,  /* jgti : 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_JLT_INT,  /* jlti : 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_JLE_INT,  /* jlei : 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_JGE_INT,  /* jgei : 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_JEQ_UINT, /* jequ : jump to address dest if src1 as int == src2 as uint */
 | 
					  OP_JGE_INT,        /* jgei : jump to address dest if src1 as int >= src2 as int*/
 | 
				
			||||||
  OP_JGT_UINT, /* jgtu : 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_JLT_UINT, /* jltu : 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_JLE_UINT, /* jleu : 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_JGE_UINT, /* jgeu : 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_JEQ_REAL, /* jeqr : jump to address dest if src1 as real == src2 as real */
 | 
					  OP_JGE_UINT,       /* jgeu : jump to address dest if src1 as int >= src2 as uint*/
 | 
				
			||||||
  OP_JGE_REAL, /* jgtr : 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_JGT_REAL, /* jltr : 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_JLT_REAL, /* jler : 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_JLE_REAL, /* jger : 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_STRLEN, /* strl : dest = length of str at src1 ptr */
 | 
					  OP_JLE_REAL,       /* jger : jump to address dest if src1 as real <= src2 as real */
 | 
				
			||||||
 | 
					  OP_STRLEN,         /* strl : dest = length of str at src1 ptr */
 | 
				
			||||||
 | 
					  OP_STREQ,          /* steq : dest = src1 ptr string == src2 ptr string */
 | 
				
			||||||
 | 
					  OP_STRCAT,         /* scat : dest = ptr of src1 ptr string + src2 ptr string */
 | 
				
			||||||
 | 
					  OP_STR_GET_CHAR,   /* sgch : dest = ptr of src1 ptr string, src2 index of string */
 | 
				
			||||||
 | 
					  OP_STR_FIND_CHAR,  /* sfch : dest = ptr of src1 ptr string, src2 uint8 char */
 | 
				
			||||||
 | 
					  OP_STR_SLICE,      /* ssli : dest = ptr of src1 ptr string, src2 start index, src3 end index */
 | 
				
			||||||
  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_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 */
 | 
				
			||||||
} Opcode;
 | 
					} Opcode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_REGS 32
 | 
					#define MAX_REGS 32
 | 
				
			||||||
| 
						 | 
					@ -98,14 +104,14 @@ typedef struct device_s {
 | 
				
			||||||
#define STACK_SIZE 256
 | 
					#define STACK_SIZE 256
 | 
				
			||||||
#define DEVICES_SIZE 8
 | 
					#define DEVICES_SIZE 8
 | 
				
			||||||
typedef struct vm_s {
 | 
					typedef struct vm_s {
 | 
				
			||||||
  u32 pc;  /* program counter */
 | 
					  u32 pc;   /* program counter */
 | 
				
			||||||
  u32 cp;  /* code pointer (last allocated opcode) */
 | 
					  u32 cp;   /* code pointer (last allocated opcode) */
 | 
				
			||||||
  u32 fp;  /* frame pointer (current frame) */
 | 
					  u32 fp;   /* frame pointer (current frame) */
 | 
				
			||||||
  u32 sp;  /* stack pointer (top of stack) */
 | 
					  u32 sp;   /* stack pointer (top of stack) */
 | 
				
			||||||
  u32 rp;  /* return stack pointer (top of stack) */
 | 
					  u32 rp;   /* return stack pointer (top of stack) */
 | 
				
			||||||
  u32 mp;  /* memory pointer (last allocated value) */
 | 
					  u32 mp;   /* memory pointer (last allocated value) */
 | 
				
			||||||
  u32 dc;  /* device count */
 | 
					  u32 dc;   /* device count */
 | 
				
			||||||
  u32 acc; /* accumulator (temporary results like SYSCALL status) */
 | 
					  u32 flag; /* flag (temporary results like SYSCALL status) */
 | 
				
			||||||
  Frame frames[FRAMES_SIZE];    /* function call frames */
 | 
					  Frame frames[FRAMES_SIZE];    /* function call frames */
 | 
				
			||||||
  u32 stack[STACK_SIZE];        /* main stack */
 | 
					  u32 stack[STACK_SIZE];        /* main stack */
 | 
				
			||||||
  u32 return_stack[STACK_SIZE]; /* return stack (for call recursion) */
 | 
					  u32 return_stack[STACK_SIZE]; /* return stack (for call recursion) */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										25
									
								
								src/test.c
								
								
								
								
							
							
						
						
									
										25
									
								
								src/test.c
								
								
								
								
							| 
						 | 
					@ -48,16 +48,21 @@ bool compile_internal_test(const char *filename, VM *vm) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool test_simple_compile(VM *vm) {
 | 
					bool test_simple_compile(VM *vm) {
 | 
				
			||||||
  u32 ptr;
 | 
					  u32 ptr;
 | 
				
			||||||
  u32 terminal_path_addr = str_alloc(vm, "/dev/term/0", 12);
 | 
					  u32 newline_addr =
 | 
				
			||||||
 | 
					      str_alloc(vm, &vm->frames[vm->fp], "\n", 2);
 | 
				
			||||||
 | 
					  u32 terminal_path_addr =
 | 
				
			||||||
 | 
					      str_alloc(vm, &vm->frames[vm->fp], "/dev/term/0", 12);
 | 
				
			||||||
  vm->code[vm->cp++] = OP_LOAD;
 | 
					  vm->code[vm->cp++] = OP_LOAD;
 | 
				
			||||||
  vm->code[vm->cp++] = 0;
 | 
					  vm->code[vm->cp++] = 0;
 | 
				
			||||||
  ptr = real_alloc(vm, 1.0f);
 | 
					  ptr = real_alloc(vm, 1.0f);
 | 
				
			||||||
  write_u32(vm, code, vm->cp, ptr); vm->cp+=4;
 | 
					  write_u32(vm, code, vm->cp, ptr);
 | 
				
			||||||
 | 
					  vm->cp += 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  vm->code[vm->cp++] = OP_LOAD;
 | 
					  vm->code[vm->cp++] = OP_LOAD;
 | 
				
			||||||
  vm->code[vm->cp++] = 1;
 | 
					  vm->code[vm->cp++] = 1;
 | 
				
			||||||
  ptr = real_alloc(vm, 2.0f);
 | 
					  ptr = real_alloc(vm, 2.0f);
 | 
				
			||||||
  write_u32(vm, code, vm->cp, ptr); vm->cp+=4;
 | 
					  write_u32(vm, code, vm->cp, ptr);
 | 
				
			||||||
 | 
					  vm->cp += 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  vm->code[vm->cp++] = OP_ADD_REAL;
 | 
					  vm->code[vm->cp++] = OP_ADD_REAL;
 | 
				
			||||||
  vm->code[vm->cp++] = 2;
 | 
					  vm->code[vm->cp++] = 2;
 | 
				
			||||||
| 
						 | 
					@ -68,16 +73,22 @@ bool test_simple_compile(VM *vm) {
 | 
				
			||||||
  vm->code[vm->cp++] = 3;
 | 
					  vm->code[vm->cp++] = 3;
 | 
				
			||||||
  vm->code[vm->cp++] = 2;
 | 
					  vm->code[vm->cp++] = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  vm->code[vm->cp++] = OP_REAL_TO_STRING;
 | 
				
			||||||
 | 
					  vm->code[vm->cp++] = 3;
 | 
				
			||||||
 | 
					  vm->code[vm->cp++] = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  vm->code[vm->cp++] = OP_LOAD_IMM;
 | 
					  vm->code[vm->cp++] = OP_LOAD_IMM;
 | 
				
			||||||
  vm->code[vm->cp++] = 2;
 | 
					  vm->code[vm->cp++] = 2;
 | 
				
			||||||
  write_u32(vm, code, vm->cp, terminal_path_addr); vm->cp+=4;
 | 
					  write_u32(vm, code, vm->cp, terminal_path_addr);
 | 
				
			||||||
 | 
					  vm->cp += 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  vm->code[vm->cp++] = OP_STRLEN;
 | 
					  vm->code[vm->cp++] = OP_STRLEN;
 | 
				
			||||||
  vm->code[vm->cp++] = 4;
 | 
					  vm->code[vm->cp++] = 4;
 | 
				
			||||||
  vm->code[vm->cp++] = 3;
 | 
					  vm->code[vm->cp++] = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  vm->code[vm->cp++] = OP_SYSCALL;
 | 
					  vm->code[vm->cp++] = OP_SYSCALL;
 | 
				
			||||||
  write_u32(vm, code, vm->cp, AS_UINT(SYSCALL_DEVICE_WRITE)); vm->cp+=4;
 | 
					  write_u32(vm, code, vm->cp, AS_UINT(SYSCALL_DEVICE_WRITE));
 | 
				
			||||||
 | 
					  vm->cp += 4;
 | 
				
			||||||
  vm->code[vm->cp++] = 3; /* arg_count */
 | 
					  vm->code[vm->cp++] = 3; /* arg_count */
 | 
				
			||||||
  vm->code[vm->cp++] = 2; /* first_reg */
 | 
					  vm->code[vm->cp++] = 2; /* first_reg */
 | 
				
			||||||
  /* syscall_id=WRITE, arg_count=2, start_reg=3 ; print(sum.toS()); */
 | 
					  /* syscall_id=WRITE, arg_count=2, start_reg=3 ; print(sum.toS()); */
 | 
				
			||||||
| 
						 | 
					@ -86,7 +97,9 @@ bool test_simple_compile(VM *vm) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool test_window_click_compile(VM *vm) {
 | 
					bool test_window_click_compile(VM *vm) {
 | 
				
			||||||
  u32 test_pixel_addr, loop_start, screen_path_addr = str_alloc(vm, "/dev/screen/0", 14);
 | 
					  u32 test_pixel_addr, loop_start,
 | 
				
			||||||
 | 
					      screen_path_addr =
 | 
				
			||||||
 | 
					          str_alloc(vm, &vm->frames[vm->fp], "/dev/screen/0", 14);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  vm->code[vm->cp++] = OP_LOAD; /* R0 = screen path */
 | 
					  vm->code[vm->cp++] = OP_LOAD; /* R0 = screen path */
 | 
				
			||||||
  vm->code[vm->cp++] = 0;
 | 
					  vm->code[vm->cp++] = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										180
									
								
								src/vm.c
								
								
								
								
							
							
						
						
									
										180
									
								
								src/vm.c
								
								
								
								
							| 
						 | 
					@ -3,19 +3,25 @@
 | 
				
			||||||
#include "opcodes.h"
 | 
					#include "opcodes.h"
 | 
				
			||||||
#include "str.h"
 | 
					#include "str.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* no inline fn in ANSI C :( */
 | 
					 | 
				
			||||||
#define COMPARE_AND_JUMP(type, op)                                             \
 | 
					#define COMPARE_AND_JUMP(type, op)                                             \
 | 
				
			||||||
  do {                                                                         \
 | 
					  do {                                                                         \
 | 
				
			||||||
    type value, value2;                                                        \
 | 
					    i32 cond;                                                                  \
 | 
				
			||||||
 | 
					    u32 mask, target;                                                          \
 | 
				
			||||||
 | 
					    u8 dest, src1, src2;                                                       \
 | 
				
			||||||
 | 
					    type value;                                                                \
 | 
				
			||||||
 | 
					    type value2;                                                               \
 | 
				
			||||||
    dest = read_u8(vm, code, vm->pc);                                          \
 | 
					    dest = read_u8(vm, code, vm->pc);                                          \
 | 
				
			||||||
    vm->pc++;                                                                  \
 | 
					    vm->pc++;                                                                  \
 | 
				
			||||||
    src1 = read_u8(vm, code, vm->pc);                                          \
 | 
					    src1 = read_u8(vm, code, vm->pc);                                          \
 | 
				
			||||||
    vm->pc++;                                                                  \
 | 
					    vm->pc++;                                                                  \
 | 
				
			||||||
    src2 = read_u8(vm, code, vm->pc);                                          \
 | 
					    src2 = read_u8(vm, code, vm->pc);                                          \
 | 
				
			||||||
    vm->pc++;                                                                  \
 | 
					    vm->pc++;                                                                  \
 | 
				
			||||||
    value = vm->frames[vm->fp].registers[src1];                                \
 | 
					    value = frame.registers[src1];                                             \
 | 
				
			||||||
    value2 = vm->frames[vm->fp].registers[src2];                               \
 | 
					    value2 = frame.registers[src2];                                            \
 | 
				
			||||||
    vm->pc = (value op value2) ? vm->frames[vm->fp].registers[dest] : vm->pc;  \
 | 
					    cond = !!(value op value2);                                                \
 | 
				
			||||||
 | 
					    mask = -(u32)cond;                                                         \
 | 
				
			||||||
 | 
					    target = frame.registers[dest];                                            \
 | 
				
			||||||
 | 
					    vm->pc = (target & mask) | (vm->pc & ~mask);                               \
 | 
				
			||||||
    return true;                                                               \
 | 
					    return true;                                                               \
 | 
				
			||||||
  } while (0)
 | 
					  } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,14 +33,12 @@
 | 
				
			||||||
    vm->pc++;                                                                  \
 | 
					    vm->pc++;                                                                  \
 | 
				
			||||||
    src2 = read_u8(vm, code, vm->pc);                                          \
 | 
					    src2 = read_u8(vm, code, vm->pc);                                          \
 | 
				
			||||||
    vm->pc++;                                                                  \
 | 
					    vm->pc++;                                                                  \
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] = (type)vm->frames[vm->fp]              \
 | 
					    frame.registers[dest] =                                                    \
 | 
				
			||||||
                                             .registers[src1] op(type)         \
 | 
					        (type)frame.registers[src1] op(type) frame.registers[src2];            \
 | 
				
			||||||
                                                 vm->frames[vm->fp]            \
 | 
					 | 
				
			||||||
                                             .registers[src2];                 \
 | 
					 | 
				
			||||||
    return true;                                                               \
 | 
					    return true;                                                               \
 | 
				
			||||||
  } while (0)
 | 
					  } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
u32 str_alloc(VM *vm, const char *str, u32 length) {
 | 
					u32 str_alloc(VM *vm, Frame *frame, const char *str, u32 length) {
 | 
				
			||||||
  u32 str_addr = vm->mp;
 | 
					  u32 str_addr = vm->mp;
 | 
				
			||||||
  u32 i = 0;
 | 
					  u32 i = 0;
 | 
				
			||||||
  vm->mp += 4;
 | 
					  vm->mp += 4;
 | 
				
			||||||
| 
						 | 
					@ -44,7 +48,7 @@ u32 str_alloc(VM *vm, const char *str, u32 length) {
 | 
				
			||||||
  vm->memory[vm->mp++] = '\0';
 | 
					  vm->memory[vm->mp++] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  write_u32(vm, memory, str_addr, length);
 | 
					  write_u32(vm, memory, str_addr, length);
 | 
				
			||||||
  vm->frames[vm->fp].end = vm->mp;
 | 
					  frame->end = vm->mp;
 | 
				
			||||||
  return str_addr;
 | 
					  return str_addr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,9 +59,11 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
  u8 opcode, dest, src1, src2;
 | 
					  u8 opcode, dest, src1, src2;
 | 
				
			||||||
  u32 v, ptr;
 | 
					  u32 v, ptr;
 | 
				
			||||||
  i32 value;
 | 
					  i32 value;
 | 
				
			||||||
 | 
					  Frame frame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Get current instruction & Advance to next instruction */
 | 
					  /* Get current instruction & Advance to next instruction */
 | 
				
			||||||
  opcode = vm->code[vm->pc++];
 | 
					  opcode = vm->code[vm->pc++];
 | 
				
			||||||
 | 
					  frame = vm->frames[vm->fp];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  switch (opcode) {
 | 
					  switch (opcode) {
 | 
				
			||||||
  case OP_HALT: {
 | 
					  case OP_HALT: {
 | 
				
			||||||
| 
						 | 
					@ -73,7 +79,7 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_RETURN: {
 | 
					  case OP_RETURN: {
 | 
				
			||||||
    vm->frames[vm->fp].rp = 0;           /* reset register ptr */
 | 
					    frame.rp = 0;                        /* reset register ptr */
 | 
				
			||||||
    vm->pc = vm->return_stack[--vm->rp]; /* set pc to return address */
 | 
					    vm->pc = vm->return_stack[--vm->rp]; /* set pc to return address */
 | 
				
			||||||
    vm->mp =
 | 
					    vm->mp =
 | 
				
			||||||
        vm->frames[vm->fp--].start; /* reset memory pointer to start
 | 
					        vm->frames[vm->fp--].start; /* reset memory pointer to start
 | 
				
			||||||
| 
						 | 
					@ -85,7 +91,7 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    v = read_u32(vm, code, vm->pc);
 | 
					    v = read_u32(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc += 4;
 | 
					    vm->pc += 4;
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] = v;
 | 
					    frame.registers[dest] = v;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_LOAD: {
 | 
					  case OP_LOAD: {
 | 
				
			||||||
| 
						 | 
					@ -94,7 +100,7 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    ptr = read_u32(vm, code, vm->pc);
 | 
					    ptr = read_u32(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc += 4;
 | 
					    vm->pc += 4;
 | 
				
			||||||
    v = read_u32(vm, memory, ptr);
 | 
					    v = read_u32(vm, memory, ptr);
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] = v;
 | 
					    frame.registers[dest] = v;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_STORE: {
 | 
					  case OP_STORE: {
 | 
				
			||||||
| 
						 | 
					@ -102,20 +108,20 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    ptr = read_u32(vm, code, vm->pc);
 | 
					    ptr = read_u32(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc += 4;
 | 
					    vm->pc += 4;
 | 
				
			||||||
    v = vm->frames[vm->fp].registers[src1];
 | 
					    v = frame.registers[src1];
 | 
				
			||||||
    write_u32(vm, memory, ptr, v);
 | 
					    write_u32(vm, memory, ptr, v);
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_PUSH: {
 | 
					  case OP_PUSH: {
 | 
				
			||||||
    dest = read_u8(vm, code, vm->pc);
 | 
					    dest = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    vm->stack[++vm->sp] = vm->frames[vm->fp].registers[dest];
 | 
					    vm->stack[++vm->sp] = frame.registers[dest];
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_POP: {
 | 
					  case OP_POP: {
 | 
				
			||||||
    dest = read_u8(vm, code, vm->pc);
 | 
					    dest = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] = vm->stack[vm->sp--];
 | 
					    frame.registers[dest] = vm->stack[vm->sp--];
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_REG_MOV: {
 | 
					  case OP_REG_MOV: {
 | 
				
			||||||
| 
						 | 
					@ -123,13 +129,21 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    src1 = read_u8(vm, code, vm->pc);
 | 
					    src1 = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] = vm->frames[vm->fp].registers[src1];
 | 
					    frame.registers[dest] = frame.registers[src1];
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_JMP: {
 | 
					  case OP_JMP: {
 | 
				
			||||||
    dest = read_u8(vm, code, vm->pc);
 | 
					    dest = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    vm->pc = vm->frames[vm->fp].registers[dest]; /* Jump to address */
 | 
					    vm->pc = frame.registers[dest]; /* Jump to address */
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  case OP_JMPF: { /* error handling for syscall, jump if flag == 0 */
 | 
				
			||||||
 | 
					    u32 mask;
 | 
				
			||||||
 | 
					    dest = read_u8(vm, code, vm->pc);
 | 
				
			||||||
 | 
					    vm->pc++;
 | 
				
			||||||
 | 
					    mask = -(u32)(vm->flag == 0);
 | 
				
			||||||
 | 
					    vm->pc = (dest & mask) | (vm->pc & ~mask);
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_SYSCALL: {
 | 
					  case OP_SYSCALL: {
 | 
				
			||||||
| 
						 | 
					@ -148,22 +162,21 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
      if (arg_count >= 2) {
 | 
					      if (arg_count >= 2) {
 | 
				
			||||||
        Device *dev;
 | 
					        Device *dev;
 | 
				
			||||||
        u32 path_ptr, mode;
 | 
					        u32 path_ptr, mode;
 | 
				
			||||||
        path_ptr =
 | 
					        path_ptr = frame.registers[first_reg]; /* R0: path pointer */
 | 
				
			||||||
            vm->frames[vm->fp].registers[first_reg]; /* R0: path pointer */
 | 
					        mode = frame.registers[first_reg + 1]; /* R1: mode */
 | 
				
			||||||
        mode = vm->frames[vm->fp].registers[first_reg + 1]; /* R1: mode */
 | 
					 | 
				
			||||||
        dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
 | 
					        dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (dev) {
 | 
					        if (dev) {
 | 
				
			||||||
          if (dev->ops->open) {
 | 
					          if (dev->ops->open) {
 | 
				
			||||||
            vm->acc = dev->ops->open(dev->data, mode);
 | 
					            vm->flag = dev->ops->open(dev->data, mode);
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            vm->acc = 1; /* success, no open needed */
 | 
					            vm->flag = 1; /* success, no open needed */
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          vm->acc = 0; /* error */
 | 
					          vm->flag = 0; /* error */
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        vm->acc = 0; /* error: not enough arguments */
 | 
					        vm->flag = 0; /* error: not enough arguments */
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -173,44 +186,40 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
        Device *dev;
 | 
					        Device *dev;
 | 
				
			||||||
        u32 path_ptr, buffer_ptr, size;
 | 
					        u32 path_ptr, buffer_ptr, size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        path_ptr =
 | 
					        path_ptr = frame.registers[first_reg];       /* R0: path pointer */
 | 
				
			||||||
            vm->frames[vm->fp].registers[first_reg]; /* R0: path pointer */
 | 
					        buffer_ptr = frame.registers[first_reg + 1]; /* R1: buffer pointer */
 | 
				
			||||||
        buffer_ptr = vm->frames[vm->fp]
 | 
					        size = frame.registers[first_reg + 2];       /* R2: size */
 | 
				
			||||||
                         .registers[first_reg + 1]; /* R1: buffer pointer */
 | 
					 | 
				
			||||||
        size = vm->frames[vm->fp].registers[first_reg + 2]; /* R2: size */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
 | 
					        dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
 | 
				
			||||||
        if (dev && dev->ops->read) {
 | 
					        if (dev && dev->ops->read) {
 | 
				
			||||||
          vm->acc =
 | 
					          vm->flag =
 | 
				
			||||||
              dev->ops->read(dev->data, (u8 *)&vm->memory[buffer_ptr], size);
 | 
					              dev->ops->read(dev->data, (u8 *)&vm->memory[buffer_ptr], size);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          vm->acc = 0;
 | 
					          vm->flag = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        vm->acc = 0; /* error: not enough arguments */
 | 
					        vm->flag = 0; /* error: not enough arguments */
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case SYSCALL_DEVICE_WRITE: {
 | 
					    case SYSCALL_DEVICE_WRITE: {
 | 
				
			||||||
      if (arg_count >= 2) {
 | 
					      if (arg_count >= 3) {
 | 
				
			||||||
        Device *dev;
 | 
					        Device *dev;
 | 
				
			||||||
        u32 path_ptr, buffer_ptr, size;
 | 
					        u32 path_ptr, buffer_ptr, size;
 | 
				
			||||||
        path_ptr =
 | 
					        path_ptr = frame.registers[first_reg];       /* R0: path pointer */
 | 
				
			||||||
            vm->frames[vm->fp].registers[first_reg]; /* R0: path pointer */
 | 
					        buffer_ptr = frame.registers[first_reg + 1]; /* R1: buffer pointer */
 | 
				
			||||||
        buffer_ptr = vm->frames[vm->fp]
 | 
					        size = frame.registers[first_reg + 2];       /* R2: size */
 | 
				
			||||||
                         .registers[first_reg + 1]; /* R1: buffer pointer */
 | 
					 | 
				
			||||||
        size = vm->frames[vm->fp].registers[first_reg + 2];  /* R2: size */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
 | 
					        dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
 | 
				
			||||||
        if (dev && dev->ops->write) {
 | 
					        if (dev && dev->ops->write) {
 | 
				
			||||||
          vm->acc = dev->ops->write(dev->data, (const u8 *)&vm->memory[buffer_ptr + 4],
 | 
					          vm->flag = dev->ops->write(
 | 
				
			||||||
                                    size);
 | 
					              dev->data, (const u8 *)&vm->memory[buffer_ptr + 4], size);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          vm->acc = 0;
 | 
					          vm->flag = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        vm->acc = 0; /* error: not enough arguments */
 | 
					        vm->flag = 0; /* error: not enough arguments */
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -219,19 +228,18 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
      if (arg_count >= 1) {
 | 
					      if (arg_count >= 1) {
 | 
				
			||||||
        Device *dev;
 | 
					        Device *dev;
 | 
				
			||||||
        u32 path_ptr;
 | 
					        u32 path_ptr;
 | 
				
			||||||
        path_ptr =
 | 
					        path_ptr = frame.registers[first_reg]; /* R0: path pointer */
 | 
				
			||||||
            vm->frames[vm->fp].registers[first_reg]; /* R0: path pointer */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
 | 
					        dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (dev && dev->ops->close) {
 | 
					        if (dev && dev->ops->close) {
 | 
				
			||||||
          i32 result = dev->ops->close(dev->data);
 | 
					          i32 result = dev->ops->close(dev->data);
 | 
				
			||||||
          vm->acc = result;
 | 
					          vm->flag = result;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          vm->acc = 0;
 | 
					          vm->flag = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        vm->acc = 0; /* error: not enough arguments */
 | 
					        vm->flag = 0; /* error: not enough arguments */
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -240,23 +248,20 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
      if (arg_count >= 3) {
 | 
					      if (arg_count >= 3) {
 | 
				
			||||||
        Device *dev;
 | 
					        Device *dev;
 | 
				
			||||||
        u32 path_ptr, args_ptr, cmd;
 | 
					        u32 path_ptr, args_ptr, cmd;
 | 
				
			||||||
        path_ptr =
 | 
					        path_ptr = frame.registers[first_reg];     /* R0: device path */
 | 
				
			||||||
            vm->frames[vm->fp].registers[first_reg]; /* R0: device path */
 | 
					        cmd = frame.registers[first_reg + 1];      /* R1: ioctl command */
 | 
				
			||||||
        cmd =
 | 
					        args_ptr = frame.registers[first_reg + 2]; /* R2: args pointer */
 | 
				
			||||||
            vm->frames[vm->fp].registers[first_reg + 1]; /* R1: ioctl command */
 | 
					 | 
				
			||||||
        args_ptr =
 | 
					 | 
				
			||||||
            vm->frames[vm->fp].registers[first_reg + 2]; /* R2: args pointer */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
 | 
					        dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (dev && dev->ops && dev->ops->ioctl) {
 | 
					        if (dev && dev->ops && dev->ops->ioctl) {
 | 
				
			||||||
          i32 result = dev->ops->ioctl(dev->data, cmd, &vm->memory[args_ptr]);
 | 
					          i32 result = dev->ops->ioctl(dev->data, cmd, &vm->memory[args_ptr]);
 | 
				
			||||||
          vm->acc = result;
 | 
					          vm->flag = result;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          vm->acc = 0; /* error or no ioctl support */
 | 
					          vm->flag = 0; /* error or no ioctl support */
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        vm->acc = 0; /* error: not enough arguments */
 | 
					        vm->flag = 0; /* error: not enough arguments */
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -266,7 +271,7 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    default: {
 | 
					    default: {
 | 
				
			||||||
      vm->acc = 0; /* unknown syscall */
 | 
					      vm->flag = 0; /* unknown syscall */
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -295,9 +300,8 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    src2 = read_u8(vm, code, vm->pc);
 | 
					    src2 = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] = (vm->frames[vm->fp].registers[src1] *
 | 
					    frame.registers[dest] =
 | 
				
			||||||
                                          vm->frames[vm->fp].registers[src2]) >>
 | 
					        (frame.registers[src1] * frame.registers[src2]) >> 16;
 | 
				
			||||||
                                         16;
 | 
					 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -308,9 +312,8 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    src2 = read_u8(vm, code, vm->pc);
 | 
					    src2 = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] =
 | 
					    frame.registers[dest] =
 | 
				
			||||||
        (vm->frames[vm->fp].registers[src1] << 16) /
 | 
					        (frame.registers[src1] << 16) / frame.registers[src2];
 | 
				
			||||||
        vm->frames[vm->fp].registers[src2];
 | 
					 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -321,8 +324,7 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    src2 = read_u8(vm, code, vm->pc);
 | 
					    src2 = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] =
 | 
					    frame.registers[dest] = frame.registers[src1] + frame.registers[src2];
 | 
				
			||||||
        vm->frames[vm->fp].registers[src1] + vm->frames[vm->fp].registers[src2];
 | 
					 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -333,8 +335,7 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    src2 = read_u8(vm, code, vm->pc);
 | 
					    src2 = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] =
 | 
					    frame.registers[dest] = frame.registers[src1] - frame.registers[src2];
 | 
				
			||||||
        vm->frames[vm->fp].registers[src1] - vm->frames[vm->fp].registers[src2];
 | 
					 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_REAL_TO_INT: {
 | 
					  case OP_REAL_TO_INT: {
 | 
				
			||||||
| 
						 | 
					@ -342,12 +343,12 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    src1 = read_u8(vm, code, vm->pc);
 | 
					    src1 = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    value = vm->frames[vm->fp].registers[src1];
 | 
					    value = frame.registers[src1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (value >= 0) {
 | 
					    if (value >= 0) {
 | 
				
			||||||
      vm->frames[vm->fp].registers[dest] = value >> 16;
 | 
					      frame.registers[dest] = value >> 16;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      vm->frames[vm->fp].registers[dest] = -((-value) >> 16);
 | 
					      frame.registers[dest] = -((-value) >> 16);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
| 
						 | 
					@ -357,8 +358,7 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    src1 = read_u8(vm, code, vm->pc);
 | 
					    src1 = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] =
 | 
					    frame.registers[dest] = (frame.registers[src1] << 16);
 | 
				
			||||||
        (vm->frames[vm->fp].registers[src1] << 16);
 | 
					 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_REAL_TO_UINT: {
 | 
					  case OP_REAL_TO_UINT: {
 | 
				
			||||||
| 
						 | 
					@ -366,11 +366,11 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    src1 = read_u8(vm, code, vm->pc);
 | 
					    src1 = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    value = vm->frames[vm->fp].registers[src1];
 | 
					    value = frame.registers[src1];
 | 
				
			||||||
    if (value < 0) {
 | 
					    if (value < 0) {
 | 
				
			||||||
      vm->frames[vm->fp].registers[dest] = 0;
 | 
					      frame.registers[dest] = 0;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      vm->frames[vm->fp].registers[dest] = AS_UINT(value >> 16);
 | 
					      frame.registers[dest] = AS_UINT(value >> 16);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -379,8 +379,7 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    src1 = read_u8(vm, code, vm->pc);
 | 
					    src1 = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] =
 | 
					    frame.registers[dest] = AS_INT(frame.registers[src1] << 16);
 | 
				
			||||||
        AS_INT(vm->frames[vm->fp].registers[src1] << 16);
 | 
					 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_JEQ_UINT: {
 | 
					  case OP_JEQ_UINT: {
 | 
				
			||||||
| 
						 | 
					@ -434,9 +433,9 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    src1 = read_u8(vm, code, vm->pc);
 | 
					    src1 = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    int_to_string(AS_INT(vm->frames[vm->fp].registers[src1]), buffer);
 | 
					    int_to_string(AS_INT(frame.registers[src1]), buffer);
 | 
				
			||||||
    ptr = str_alloc(vm, buffer, strlen(buffer));
 | 
					    ptr = str_alloc(vm, &frame, buffer, strlen(buffer));
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] = ptr;
 | 
					    frame.registers[dest] = ptr;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_UINT_TO_STRING: {
 | 
					  case OP_UINT_TO_STRING: {
 | 
				
			||||||
| 
						 | 
					@ -445,9 +444,9 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    src1 = read_u8(vm, code, vm->pc);
 | 
					    src1 = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    uint_to_string(vm->frames[vm->fp].registers[src1], buffer);
 | 
					    uint_to_string(frame.registers[src1], buffer);
 | 
				
			||||||
    ptr = str_alloc(vm, buffer, strlen(buffer));
 | 
					    ptr = str_alloc(vm, &frame, buffer, strlen(buffer));
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] = ptr;
 | 
					    frame.registers[dest] = ptr;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_REAL_TO_STRING: {
 | 
					  case OP_REAL_TO_STRING: {
 | 
				
			||||||
| 
						 | 
					@ -456,9 +455,10 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    src1 = read_u8(vm, code, vm->pc);
 | 
					    src1 = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
    fixed_to_string(AS_INT(vm->frames[vm->fp].registers[src1]), buffer);
 | 
					    fixed_to_string(AS_INT(frame.registers[src1]), buffer);
 | 
				
			||||||
    ptr = str_alloc(vm, buffer, strlen(buffer)); /* copy buffer to dest */
 | 
					    ptr =
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] = ptr;
 | 
					        str_alloc(vm, &frame, buffer, strlen(buffer)); /* copy buffer to dest */
 | 
				
			||||||
 | 
					    frame.registers[dest] = ptr;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_STRLEN: {
 | 
					  case OP_STRLEN: {
 | 
				
			||||||
| 
						 | 
					@ -468,9 +468,9 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    src1 = read_u8(vm, code, vm->pc);
 | 
					    src1 = read_u8(vm, code, vm->pc);
 | 
				
			||||||
    vm->pc++;
 | 
					    vm->pc++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ptr = vm->frames[vm->fp].registers[src1];
 | 
					    ptr = frame.registers[src1];
 | 
				
			||||||
    length = read_u32(vm, memory, ptr);
 | 
					    length = read_u32(vm, memory, ptr);
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest] = length;
 | 
					    frame.registers[dest] = length;
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case OP_STRING_TO_INT: {
 | 
					  case OP_STRING_TO_INT: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								src/vm.h
								
								
								
								
							
							
						
						
									
										2
									
								
								src/vm.h
								
								
								
								
							| 
						 | 
					@ -4,7 +4,7 @@
 | 
				
			||||||
#include "opcodes.h"
 | 
					#include "opcodes.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool step_vm(VM *vm);
 | 
					bool step_vm(VM *vm);
 | 
				
			||||||
u32 str_alloc(VM *vm, const char *str, u32 length);
 | 
					u32 str_alloc(VM *vm, Frame *frame, const char *str, u32 length);
 | 
				
			||||||
void fixed_to_string(i32 value, char *buffer);
 | 
					void fixed_to_string(i32 value, char *buffer);
 | 
				
			||||||
void int_to_string(i32 value, char *buffer);
 | 
					void int_to_string(i32 value, char *buffer);
 | 
				
			||||||
void uint_to_string(u32 value, char *buffer);
 | 
					void uint_to_string(u32 value, char *buffer);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue