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