update to opcodes, go with tunnels and syscals, partial refactor of memory, try out fixed size again
This commit is contained in:
parent
0dedf5a2ad
commit
43ebed6553
|
@ -1,4 +1,5 @@
|
|||
#include "compiler.h"
|
||||
#include "vm.h"
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
|
@ -33,6 +34,8 @@ typedef struct {
|
|||
Parser parser;
|
||||
SymbolTable st;
|
||||
|
||||
const char *internalErrorMsg = "FLAGRANT COMPILER ERROR\n\nCompiler over.\nBug = Very Yes.";
|
||||
|
||||
void errorAt(Token *token, const char *message) {
|
||||
if (parser.panicMode)
|
||||
return;
|
||||
|
@ -99,17 +102,17 @@ void number(VM *vm) {
|
|||
char *endptr;
|
||||
int32_t value = (int32_t)strtol(parser.previous.start, &endptr, 10);
|
||||
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;
|
||||
} else if (parser.previous.type == TOKEN_UINT_LITERAL) {
|
||||
long value = atol(parser.previous.start);
|
||||
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;
|
||||
} else if (parser.previous.type == TOKEN_FLOAT_LITERAL) {
|
||||
float value = atof(parser.previous.start);
|
||||
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;
|
||||
}
|
||||
errorAtCurrent("Invalid number format");
|
||||
|
@ -128,7 +131,7 @@ void string(VM *vm) {
|
|||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,10 +27,8 @@ typedef struct symbol_t {
|
|||
};
|
||||
int8_t reg;
|
||||
uint8_t flags[3]; /* only use for padding now, might be used later*/
|
||||
union {
|
||||
uint32_t frame;
|
||||
uint32_t ptr;
|
||||
};
|
||||
} Symbol;
|
||||
|
||||
#define MODULE_NAME_SIZE 32
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
148
src/opcodes.h
148
src/opcodes.h
|
@ -3,6 +3,67 @@
|
|||
|
||||
#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 {
|
||||
int32_t i; /* Integers */
|
||||
float f; /* Float */
|
||||
|
@ -42,12 +103,21 @@ typedef struct keyboard_t {
|
|||
const uint8_t *keys;
|
||||
} Keyboard;
|
||||
|
||||
typedef enum {
|
||||
SCREEN,
|
||||
MOUSE,
|
||||
KEYBOARD,
|
||||
CONTROLLER,
|
||||
AUDIO,
|
||||
TUNNEL,
|
||||
} Devicecode;
|
||||
|
||||
typedef union device_u {
|
||||
uint8_t type;
|
||||
Screen s;
|
||||
Mouse m;
|
||||
Keyboard k;
|
||||
/* File f; */
|
||||
/* Audio a; */
|
||||
/* Tunnel t; */
|
||||
} Device;
|
||||
|
||||
|
@ -78,80 +148,4 @@ typedef struct vm_s {
|
|||
Value memory[MEMORY_SIZE]; /* memory block */
|
||||
} 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
|
||||
|
|
127
src/vm.c
127
src/vm.c
|
@ -98,63 +98,22 @@ bool step_vm(VM *vm) {
|
|||
of old slice, pop the frame */
|
||||
return true;
|
||||
}
|
||||
case OP_LOADI: {
|
||||
case OP_LOAD: {
|
||||
uint32_t ptr = vm->code[vm->pc++].u;
|
||||
int32_t v = vm->memory[ptr].i;
|
||||
vm->frames[vm->fp].registers[dest].i = v;
|
||||
vm->frames[vm->fp].registers[dest] = vm->memory[ptr];
|
||||
return true;
|
||||
}
|
||||
case OP_LOADU: {
|
||||
case OP_STORE: {
|
||||
uint32_t ptr = vm->code[vm->pc++].u;
|
||||
uint32_t v = vm->memory[ptr].u;
|
||||
vm->frames[vm->fp].registers[dest].u = v;
|
||||
vm->memory[ptr] = vm->frames[vm->fp].registers[src1];
|
||||
return true;
|
||||
}
|
||||
case OP_LOADF: {
|
||||
uint32_t ptr = vm->code[vm->pc++].u;
|
||||
float v = vm->memory[ptr].f;
|
||||
vm->frames[vm->fp].registers[dest].f = v;
|
||||
case OP_PUSH: {
|
||||
vm->stack[++vm->sp] = vm->frames[vm->fp].registers[dest];
|
||||
return true;
|
||||
}
|
||||
case OP_LOADP: {
|
||||
uint32_t ptr = vm->code[vm->pc++].u;
|
||||
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;
|
||||
case OP_POP: {
|
||||
vm->frames[vm->fp].registers[dest] = vm->stack[vm->sp--];
|
||||
return true;
|
||||
}
|
||||
case OP_ADD_INT:
|
||||
|
@ -263,10 +222,6 @@ bool step_vm(VM *vm) {
|
|||
case OP_JLE_REAL: {
|
||||
COMPARE_AND_JUMP(float, u, <=);
|
||||
}
|
||||
case OP_NOT: {
|
||||
/* TODO implement not */
|
||||
return false;
|
||||
}
|
||||
case OP_INT_TO_STRING: {
|
||||
int32_t a = (int32_t)vm->frames[vm->fp].registers[src1].i; /* get value */
|
||||
char buffer[32];
|
||||
|
@ -291,48 +246,6 @@ bool step_vm(VM *vm) {
|
|||
vm->frames[vm->fp].registers[dest].u = ptr;
|
||||
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: {
|
||||
uint32_t addr1 = (uint32_t)vm->frames[vm->fp].registers[src1].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 */
|
||||
vm->frames[vm->fp].registers[dest].u =
|
||||
mem_dest; /* store ptr of array to dest register */
|
||||
uint32_t length = vm->code[vm->pc++].u;
|
||||
vm->memory[mem_dest].u = length;
|
||||
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++];
|
||||
}
|
||||
}
|
||||
uint32_t size = (uint32_t)vm->frames[vm->fp].registers[src1].u;
|
||||
vm->memory[mem_dest].u = size;
|
||||
vm->frames[vm->fp].allocated.end +=
|
||||
length; /* increment to end of allocated */
|
||||
size; /* increment to end of allocated */
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
case OP_MEM_SWAP: {
|
||||
vm->memory[dest].u ^= vm->memory[src1].u;
|
||||
vm->memory[src1].u ^= vm->memory[dest].u;
|
||||
vm->memory[dest].u ^= vm->memory[src1].u;
|
||||
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].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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue