update to opcodes, go with tunnels and syscals, partial refactor of memory, try out fixed size again

This commit is contained in:
zongor 2025-08-29 22:02:19 -07:00
parent 0dedf5a2ad
commit 43ebed6553
6 changed files with 355 additions and 193 deletions

View File

@ -1,4 +1,5 @@
#include "compiler.h" #include "compiler.h"
#include "vm.h"
#include <stdio.h> #include <stdio.h>
typedef struct { typedef struct {
@ -33,6 +34,8 @@ typedef struct {
Parser parser; Parser parser;
SymbolTable st; SymbolTable st;
const char *internalErrorMsg = "FLAGRANT COMPILER ERROR\n\nCompiler over.\nBug = Very Yes.";
void errorAt(Token *token, const char *message) { void errorAt(Token *token, const char *message) {
if (parser.panicMode) if (parser.panicMode)
return; return;
@ -99,17 +102,17 @@ void number(VM *vm) {
char *endptr; char *endptr;
int32_t value = (int32_t)strtol(parser.previous.start, &endptr, 10); int32_t value = (int32_t)strtol(parser.previous.start, &endptr, 10);
emitOp(vm, OP_LOADI, vm->frames[vm->fp].rp++, 0, 0); emitOp(vm, OP_LOADI, vm->frames[vm->fp].rp++, 0, 0);
vm->code[vm->cp++].i = value; vm->code[vm->cp++].u = int_alloc(vm, value);
return; return;
} else if (parser.previous.type == TOKEN_UINT_LITERAL) { } else if (parser.previous.type == TOKEN_UINT_LITERAL) {
long value = atol(parser.previous.start); long value = atol(parser.previous.start);
emitOp(vm, OP_LOADU, vm->frames[vm->fp].rp++, 0, 0); emitOp(vm, OP_LOADU, vm->frames[vm->fp].rp++, 0, 0);
vm->code[vm->cp++].u = value; vm->code[vm->cp++].u = nat_alloc(vm, value);
return; return;
} else if (parser.previous.type == TOKEN_FLOAT_LITERAL) { } else if (parser.previous.type == TOKEN_FLOAT_LITERAL) {
float value = atof(parser.previous.start); float value = atof(parser.previous.start);
emitOp(vm, OP_LOADF, vm->frames[vm->fp].rp++, 0, 0); emitOp(vm, OP_LOADF, vm->frames[vm->fp].rp++, 0, 0);
vm->code[vm->cp++].f = value; vm->code[vm->cp++].u = real_alloc(vm, value);
return; return;
} }
errorAtCurrent("Invalid number format"); errorAtCurrent("Invalid number format");
@ -128,7 +131,7 @@ void string(VM *vm) {
} }
} }
vm->frames[vm->fp].allocated.end += length / 4; vm->frames[vm->fp].allocated.end += length / 4;
emitOp(vm, OP_LOADU, vm->frames[vm->fp].rp++, 0, 0); emitOp(vm, OP_LOADP, vm->frames[vm->fp].rp++, 0, 0);
vm->code[vm->cp++].u = str_addr; vm->code[vm->cp++].u = str_addr;
} }

View File

@ -27,10 +27,8 @@ typedef struct symbol_t {
}; };
int8_t reg; int8_t reg;
uint8_t flags[3]; /* only use for padding now, might be used later*/ uint8_t flags[3]; /* only use for padding now, might be used later*/
union { uint32_t frame;
uint32_t frame; uint32_t ptr;
uint32_t ptr;
};
} Symbol; } Symbol;
#define MODULE_NAME_SIZE 32 #define MODULE_NAME_SIZE 32

201
src/fixed.c Normal file
View File

@ -0,0 +1,201 @@
/* fixed.c - Q16.16 Fixed-Point Math Implementation */
#include "fixed.h"
/* Conversion functions */
fixed_t int_to_fixed(int32_t i) {
return i << 16;
}
int32_t fixed_to_int(fixed_t f) {
return f >> 16;
}
fixed_t float_to_fixed(float f) {
return (fixed_t)(f * 65536.0f);
}
float fixed_to_float(fixed_t f) {
return (float)f / 65536.0f;
}
fixed_t fixed_add(fixed_t a, fixed_t b) {
return a + b;
}
fixed_t fixed_sub(fixed_t a, fixed_t b) {
return a - b;
}
fixed_t fixed_mul(fixed_t a, fixed_t b) {
/* Extract high and low parts */
int32_t a_hi = a >> 16;
uint32_t a_lo = (uint32_t)a & 0xFFFFU;
int32_t b_hi = b >> 16;
uint32_t b_lo = (uint32_t)b & 0xFFFFU;
/* Compute partial products */
int32_t p0 = (int32_t)(a_lo * b_lo) >> 16; /* Low * Low */
int32_t p1 = a_hi * (int32_t)b_lo; /* High * Low */
int32_t p2 = (int32_t)a_lo * b_hi; /* Low * High */
int32_t p3 = (a_hi * b_hi) << 16; /* High * High */
/* Combine results */
return p0 + p1 + p2 + p3;
}
fixed_t fixed_div(fixed_t a, fixed_t b) {
if (b == 0) return 0; /* Handle division by zero */
/* Determine sign */
int negative = ((a < 0) ^ (b < 0));
/* Work with absolute values */
uint32_t ua = (a < 0) ? -a : a;
uint32_t ub = (b < 0) ? -b : b;
/* Perform division using long division in base 2^16 */
uint32_t quotient = 0;
uint32_t remainder = 0;
int i;
for (i = 0; i < 32; i++) {
remainder <<= 1;
if (ua & 0x80000000U) {
remainder |= 1;
}
ua <<= 1;
if (remainder >= ub) {
remainder -= ub;
quotient |= 1;
}
if (i < 31) {
quotient <<= 1;
}
}
return negative ? -(int32_t)quotient : (int32_t)quotient;
}
int fixed_eq(fixed_t a, fixed_t b) {
return a == b;
}
int fixed_ne(fixed_t a, fixed_t b) {
return a != b;
}
int fixed_lt(fixed_t a, fixed_t b) {
return a < b;
}
int fixed_le(fixed_t a, fixed_t b) {
return a <= b;
}
int fixed_gt(fixed_t a, fixed_t b) {
return a > b;
}
int fixed_ge(fixed_t a, fixed_t b) {
return a >= b;
}
/* Unary operations */
fixed_t fixed_neg(fixed_t f) {
return -f;
}
fixed_t fixed_abs(fixed_t f) {
return (f < 0) ? -f : f;
}
/* Square root using Newton-Raphson method */
fixed_t fixed_sqrt(fixed_t f) {
if (f <= 0) return 0;
fixed_t x = f;
fixed_t prev;
/* Newton-Raphson iteration: x = (x + f/x) / 2 */
do {
prev = x;
x = fixed_div(fixed_add(x, fixed_div(f, x)), int_to_fixed(2));
} while (fixed_gt(fixed_abs(fixed_sub(x, prev)), 1)); /* Precision to 1/65536 */
return x;
}
/* Sine function using Taylor series */
fixed_t fixed_sin(fixed_t f) {
/* Normalize angle to [-π, π] */
fixed_t pi2 = fixed_mul(FIXED_PI, int_to_fixed(2));
while (fixed_gt(f, FIXED_PI)) f = fixed_sub(f, pi2);
while (fixed_lt(f, fixed_neg(FIXED_PI))) f = fixed_add(f, pi2);
/* Taylor series: sin(x) = x - x³/3! + x⁵/5! - x⁷/7! + ... */
fixed_t result = f;
fixed_t term = f;
fixed_t f_squared = fixed_mul(f, f);
/* Calculate first few terms for reasonable precision */
int i;
for (i = 3; i <= 11; i += 2) {
term = fixed_mul(term, f_squared);
term = fixed_div(term, int_to_fixed(i * (i - 1)));
if ((i / 2) % 2 == 0) {
result = fixed_add(result, term);
} else {
result = fixed_sub(result, term);
}
}
return result;
}
/* Cosine function using Taylor series */
fixed_t fixed_cos(fixed_t f) {
/* cos(x) = 1 - x²/2! + x⁴/4! - x⁶/6! + ... */
fixed_t result = FIXED_ONE;
fixed_t term = FIXED_ONE;
fixed_t f_squared = fixed_mul(f, f);
int i;
for (i = 2; i <= 12; i += 2) {
term = fixed_mul(term, f_squared);
term = fixed_div(term, int_to_fixed(i * (i - 1)));
if ((i / 2) % 2 == 0) {
result = fixed_add(result, term);
} else {
result = fixed_sub(result, term);
}
}
return result;
}
/* Tangent function */
fixed_t fixed_tan(fixed_t f) {
fixed_t cos_val = fixed_cos(f);
if (cos_val == 0) return 0; /* Handle undefined case */
return fixed_div(fixed_sin(f), cos_val);
}
/* Utility functions */
fixed_t fixed_min(fixed_t a, fixed_t b) {
return (a < b) ? a : b;
}
fixed_t fixed_max(fixed_t a, fixed_t b) {
return (a > b) ? a : b;
}
fixed_t fixed_clamp(fixed_t f, fixed_t min_val, fixed_t max_val) {
if (f < min_val) return min_val;
if (f > max_val) return max_val;
return f;
}

55
src/fixed.h Normal file
View File

@ -0,0 +1,55 @@
/* fixed.h - Q16.16 Fixed-Point Math Library in C89 */
#ifndef FIXED_H
#define FIXED_H
#include <stdint.h>
/* Q16.16 fixed-point type */
typedef int32_t fixed_t;
/* Constants */
#define FIXED_ONE 0x00010000L /* 1.0 in Q16.16 */
#define FIXED_ZERO 0x00000000L /* 0.0 in Q16.16 */
#define FIXED_HALF 0x00008000L /* 0.5 in Q16.16 */
#define FIXED_PI 0x0003243FL /* π ≈ 3.14159 */
#define FIXED_E 0x0002B7E1L /* e ≈ 2.71828 */
#define FIXED_MAX 0x7FFFFFFFL /* Maximum positive value */
#define FIXED_MIN 0x80000000L /* Minimum negative value */
/* Conversion functions */
fixed_t int_to_fixed(int32_t i);
int32_t fixed_to_int(fixed_t f);
fixed_t float_to_fixed(float f);
float fixed_to_float(fixed_t f);
/* Basic arithmetic operations */
fixed_t fixed_add(fixed_t a, fixed_t b);
fixed_t fixed_sub(fixed_t a, fixed_t b);
fixed_t fixed_mul(fixed_t a, fixed_t b);
fixed_t fixed_div(fixed_t a, fixed_t b);
/* Comparison functions */
int fixed_eq(fixed_t a, fixed_t b);
int fixed_ne(fixed_t a, fixed_t b);
int fixed_lt(fixed_t a, fixed_t b);
int fixed_le(fixed_t a, fixed_t b);
int fixed_gt(fixed_t a, fixed_t b);
int fixed_ge(fixed_t a, fixed_t b);
/* Unary operations */
fixed_t fixed_neg(fixed_t f);
fixed_t fixed_abs(fixed_t f);
/* Advanced math functions */
fixed_t fixed_sqrt(fixed_t f);
fixed_t fixed_sin(fixed_t f); /* f in radians */
fixed_t fixed_cos(fixed_t f); /* f in radians */
fixed_t fixed_tan(fixed_t f); /* f in radians */
/* Utility functions */
fixed_t fixed_min(fixed_t a, fixed_t b);
fixed_t fixed_max(fixed_t a, fixed_t b);
fixed_t fixed_clamp(fixed_t f, fixed_t min, fixed_t max);
#endif /* FIXED_H */

View File

@ -3,6 +3,67 @@
#include "common.h" #include "common.h"
typedef enum {
OP_HALT, /* halt : terminate execution */
OP_JMP, /* jump : jump to address src1 unconditionally */
OP_CALL, /* call : creates a new frame */
OP_RETURN, /* retn : returns from a frame to the parent frame */
OP_LOAD, /* load : dest = &[next memory location] */
OP_STORE, /* stor : next memory location = src1 as float */
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_REG_MOV, /* rmov : dest = src1 */
OP_REG_SWAP, /* rswp : dest = src1, src1 = dest */
OP_MEM_SWAP, /* mswp : &dest = &src1, &src1 = &dest */
OP_MEM_MOV, /* mmov : &dest = &src1 */
OP_MEM_ALLOC, /* aloc : dest [next memory location as size] */
OP_REF, /* ref : dest = &memory[src1] */
OP_DEREF, /* dref : dest = memory[src1] */
OP_SYSCALL, /* sysc : */
OP_ADD_INT, /* addi : dest = src1 + src2 */
OP_SUB_INT, /* subi : dest = src1 - src2 */
OP_MUL_INT, /* muli : dest = src1 * src2 */
OP_DIV_INT, /* divi : dest = src1 / src2 */
OP_ADD_UINT, /* addu : dest = src1 + src2 */
OP_SUB_UINT, /* subu : dest = src1 - src2 */
OP_MUL_UINT, /* mulu : dest = src1 * src2 */
OP_DIV_UINT, /* divu : dest = src1 / src2 */
OP_ADD_REAL, /* addr : dest = src1 + src2 */
OP_SUB_REAL, /* subr : dest = src1 - src2 */
OP_MUL_REAL, /* mulr : dest = src1 * src2 */
OP_DIV_REAL, /* divr : dest = src1 / src2 */
OP_INT_TO_REAL, /* itor : 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_UINT, /* rtou : dest = src1 as uint */
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_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_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_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_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_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_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_JLE_REAL, /* jger : jump to address dest if src1 as real <= src2 as real */
OP_INT_TO_STRING, /* itos : dest = src1 as str */
OP_UINT_TO_STRING, /* utos : dest = src1 as str */
OP_REAL_TO_STRING, /* rtos : dest = src1 as str */
OP_CMP_STRING, /* cmps : dest = (str == src2) as bool */
OP_STRING_TO_INT, /* stoi : dest = src1 as int */
OP_STRING_TO_UINT, /* stou : dest = src1 as uint */
OP_STRING_TO_REAL, /* stor : dest = src1 as real */
} Opcode;
/* defines a uint32 opcode */
#define OP(opcode, dest, src1, src2) \
((opcode << 24) | (dest << 16) | (src1 << 8) | src2)
typedef union value_u { typedef union value_u {
int32_t i; /* Integers */ int32_t i; /* Integers */
float f; /* Float */ float f; /* Float */
@ -42,12 +103,21 @@ typedef struct keyboard_t {
const uint8_t *keys; const uint8_t *keys;
} Keyboard; } Keyboard;
typedef enum {
SCREEN,
MOUSE,
KEYBOARD,
CONTROLLER,
AUDIO,
TUNNEL,
} Devicecode;
typedef union device_u { typedef union device_u {
uint8_t type; uint8_t type;
Screen s; Screen s;
Mouse m; Mouse m;
Keyboard k; Keyboard k;
/* File f; */ /* Audio a; */
/* Tunnel t; */ /* Tunnel t; */
} Device; } Device;
@ -78,80 +148,4 @@ typedef struct vm_s {
Value memory[MEMORY_SIZE]; /* memory block */ Value memory[MEMORY_SIZE]; /* memory block */
} VM; } VM;
typedef enum {
OP_HALT, /* halt : terminate execution */
OP_LOADI, /* lodi : dest = next memory location as int */
OP_LOADU, /* lodu : dest = next memory location as uint */
OP_LOADF, /* lodf : dest = next memory location as float */
OP_LOADP, /* lodp : dest = &[next memory location] */
OP_STOREI, /* stri : next memory location = src1 as int */
OP_STOREU, /* stru : next memory location = src1 as uint */
OP_STOREF, /* strf : next memory location = src1 as float */
OP_PUSHI, /* pshi : push int from register onto the stack */
OP_PUSHU, /* pshu : push uint from register onto the stack */
OP_PUSHF, /* pshf : push float from register onto the stack */
OP_PUSHS, /* pshs : push str ref from register onto the stack and copy str */
OP_POPI, /* popi : pop int from stack onto the register */
OP_POPU, /* popu : pop uint from stack onto the register */
OP_POPF, /* popf : pop float from stack onto the register */
OP_POPS, /* pops : pop str ref from stack and move/copy to register */
OP_ADD_INT, /* addi : dest = src1 + src2 */
OP_SUB_INT, /* subi : dest = src1 - src2 */
OP_MUL_INT, /* muli : dest = src1 * src2 */
OP_DIV_INT, /* divi : dest = src1 / src2 */
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_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_JGE_INT, /* jgei : jump to address dest if src1 as int >= src2 as int*/
OP_INT_TO_REAL, /* itor : dest = src1 as f32 */
OP_ADD_UINT, /* addu : dest = src1 + src2 */
OP_SUB_UINT, /* subu : dest = src1 - src2 */
OP_MUL_UINT, /* mulu : dest = src1 * src2 */
OP_DIV_UINT, /* divu : dest = src1 / src2 */
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_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_JGE_UINT, /* jgeu : jump to address dest if src1 as int >= src2 as uint*/
OP_UINT_TO_REAL, /* utor : dest = src1 as f32 */
OP_ADD_REAL, /* addr : dest = src1 + src2 */
OP_SUB_REAL, /* subr : dest = src1 - src2 */
OP_MUL_REAL, /* mulr : dest = src1 * src2 */
OP_DIV_REAL, /* divr : dest = src1 / src2 */
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_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_JLE_REAL, /* jger : jump to address dest if src1 as real <= src2 as real */
OP_REAL_TO_INT, /* rtoi : dest = src1 as int */
OP_REAL_TO_UINT, /* rtou : dest = src1 as uint */
OP_REG_MOV, /* rmov : dest = src1 */
OP_REG_SWAP, /* rswp : dest = src1, src1 = dest */
OP_JMP, /* jump : jump to address src1 unconditionally */
OP_CALL, /* call : creates a new frame */
OP_RETURN, /* retn : returns from a frame to the parent frame */
OP_INT_TO_STRING, /* itos : dest = src1 as str */
OP_UINT_TO_STRING, /* utos : dest = src1 as str */
OP_REAL_TO_STRING, /* rtos : dest = src1 as str */
OP_READ_STRING, /* gets : dest = gets as str */
OP_PRINT_STRING, /* puts : write src1 to stdout */
OP_CMP_STRING, /* cmps : dest = (str == src2) as bool */
OP_NOT, /* not : dest = not src1 */
OP_MEM_ALLOC, /* alloc : dest = &ptr */
OP_MEM_SWAP, /* swap : &dest = &src1, &src1 = &dest */
OP_MEM_MOV, /* mov : &dest = &src1 */
} Opcode;
typedef enum {
SCREEN,
MOUSE,
KEYBOARD,
CONTROLLER,
AUDIO,
} Devicecode;
/* defines a uint32 opcode */
#define OP(opcode, dest, src1, src2) ((opcode << 24) | (dest << 16) | (src1 << 8) | src2)
#endif #endif

127
src/vm.c
View File

@ -98,63 +98,22 @@ bool step_vm(VM *vm) {
of old slice, pop the frame */ of old slice, pop the frame */
return true; return true;
} }
case OP_LOADI: { case OP_LOAD: {
uint32_t ptr = vm->code[vm->pc++].u; uint32_t ptr = vm->code[vm->pc++].u;
int32_t v = vm->memory[ptr].i; vm->frames[vm->fp].registers[dest] = vm->memory[ptr];
vm->frames[vm->fp].registers[dest].i = v;
return true; return true;
} }
case OP_LOADU: { case OP_STORE: {
uint32_t ptr = vm->code[vm->pc++].u; uint32_t ptr = vm->code[vm->pc++].u;
uint32_t v = vm->memory[ptr].u; vm->memory[ptr] = vm->frames[vm->fp].registers[src1];
vm->frames[vm->fp].registers[dest].u = v;
return true; return true;
} }
case OP_LOADF: { case OP_PUSH: {
uint32_t ptr = vm->code[vm->pc++].u; vm->stack[++vm->sp] = vm->frames[vm->fp].registers[dest];
float v = vm->memory[ptr].f;
vm->frames[vm->fp].registers[dest].f = v;
return true; return true;
} }
case OP_LOADP: { case OP_POP: {
uint32_t ptr = vm->code[vm->pc++].u; vm->frames[vm->fp].registers[dest] = vm->stack[vm->sp--];
vm->frames[vm->fp].registers[dest].u = ptr;
return true;
}
case OP_STOREI: {
vm->memory[vm->code[vm->pc++].u].i = vm->frames[vm->fp].registers[src1].i;
return true;
}
case OP_STOREU: {
vm->memory[vm->code[vm->pc++].u].u = vm->frames[vm->fp].registers[src1].u;
return true;
}
case OP_STOREF: {
vm->memory[vm->code[vm->pc++].u].f = vm->frames[vm->fp].registers[src1].f;
return true;
}
case OP_PUSHI: {
vm->stack[++vm->sp].i = vm->frames[vm->fp].registers[dest].i;
return true;
}
case OP_PUSHU: {
vm->stack[++vm->sp].u = vm->frames[vm->fp].registers[dest].u;
return true;
}
case OP_PUSHF: {
vm->stack[++vm->sp].f = vm->frames[vm->fp].registers[dest].f;
return true;
}
case OP_POPI: {
vm->frames[vm->fp].registers[dest].i = vm->stack[vm->sp--].i;
return true;
}
case OP_POPU: {
vm->frames[vm->fp].registers[dest].u = vm->stack[vm->sp--].u;
return true;
}
case OP_POPF: {
vm->frames[vm->fp].registers[dest].f = vm->stack[vm->sp--].f;
return true; return true;
} }
case OP_ADD_INT: case OP_ADD_INT:
@ -263,10 +222,6 @@ bool step_vm(VM *vm) {
case OP_JLE_REAL: { case OP_JLE_REAL: {
COMPARE_AND_JUMP(float, u, <=); COMPARE_AND_JUMP(float, u, <=);
} }
case OP_NOT: {
/* TODO implement not */
return false;
}
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 = (int32_t)vm->frames[vm->fp].registers[src1].i; /* get value */
char buffer[32]; char buffer[32];
@ -291,48 +246,6 @@ bool step_vm(VM *vm) {
vm->frames[vm->fp].registers[dest].u = ptr; vm->frames[vm->fp].registers[dest].u = ptr;
return true; return true;
} }
case OP_READ_STRING: {
uint32_t str_addr = vm->mp++;
uint32_t length = 0;
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) {
uint32_t idx = length % 4;
vm->memory[vm->mp].c[idx] = (char)ch;
length++;
if (idx == 3)
vm->mp++;
}
uint32_t i, rem = length % 4;
if (rem != 0) {
for (i = rem; i < 4; i++) {
vm->memory[vm->mp].c[i] = '\0';
}
vm->mp++;
}
vm->memory[str_addr].u = length;
vm->frames[vm->fp].allocated.end = vm->mp;
vm->frames[vm->fp].registers[dest].u = str_addr;
return true;
}
case OP_PRINT_STRING: {
uint32_t ptr = (uint32_t)vm->frames[vm->fp].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 = vm->memory[str_src + (i / 4)].c[i % 4];
if (ch == '\0')
break;
putchar(ch);
}
putchar('\n');
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 = (uint32_t)vm->frames[vm->fp].registers[src1].u;
uint32_t addr2 = (uint32_t)vm->frames[vm->fp].registers[src2].u; uint32_t addr2 = (uint32_t)vm->frames[vm->fp].registers[src2].u;
@ -366,26 +279,24 @@ bool step_vm(VM *vm) {
.allocated.end; /* get start of unallocated */ .allocated.end; /* get start of unallocated */
vm->frames[vm->fp].registers[dest].u = vm->frames[vm->fp].registers[dest].u =
mem_dest; /* store ptr of array to dest register */ mem_dest; /* store ptr of array to dest register */
uint32_t length = vm->code[vm->pc++].u; uint32_t size = (uint32_t)vm->frames[vm->fp].registers[src1].u;
vm->memory[mem_dest].u = length; vm->memory[mem_dest].u = size;
if (src1) { /* if has inline data */
uint32_t i = 0;
for (i = 0; i < length; i++) {
vm->memory[mem_dest + i] = vm->code[vm->pc++];
}
}
vm->frames[vm->fp].allocated.end += vm->frames[vm->fp].allocated.end +=
length; /* increment to end of allocated */ size; /* increment to end of allocated */
return true; return true;
} }
case OP_MEM_MOV: { case OP_MEM_MOV: {
vm->memory[dest] = vm->memory[src1]; uint32_t dest_addr = (uint32_t)vm->frames[vm->fp].registers[dest].u;
uint32_t src_addr = (uint32_t)vm->frames[vm->fp].registers[src1].u;
vm->memory[dest_addr] = vm->memory[src_addr];
return true; return true;
} }
case OP_MEM_SWAP: { case OP_MEM_SWAP: {
vm->memory[dest].u ^= vm->memory[src1].u; uint32_t dest_addr = (uint32_t)vm->frames[vm->fp].registers[dest].u;
vm->memory[src1].u ^= vm->memory[dest].u; uint32_t src_addr = (uint32_t)vm->frames[vm->fp].registers[src1].u;
vm->memory[dest].u ^= vm->memory[src1].u; vm->memory[dest_addr].u ^= vm->memory[src_addr].u;
vm->memory[src_addr].u ^= vm->memory[dest_addr].u;
vm->memory[dest_addr].u ^= vm->memory[src_addr].u;
return true; return true;
} }
} }