wip compiler stuff

This commit is contained in:
zongor 2025-11-04 17:09:55 -08:00
parent edb00d0a4c
commit 5d2aa1ad22
26 changed files with 633 additions and 176 deletions

View File

@ -80,6 +80,7 @@ endif
VM_SOURCES := \
$(SRC_DIR)/vm/vm.c \
$(SRC_DIR)/vm/device.c \
$(SRC_DIR)/vm/fixed.c \
$(SRC_DIR)/vm/libc.c
ifeq ($(BUILD_MODE), release)
@ -87,13 +88,15 @@ ifeq ($(BUILD_MODE), release)
$(ARCH_DIR)/devices.c\
$(SRC_DIR)/tools/parser.c \
$(SRC_DIR)/tools/lexer.c \
$(SRC_DIR)/tools/assembler.c
$(SRC_DIR)/tools/assembler.c\
$(SRC_DIR)/tools/compiler.c
else
PLATFORM_SOURCE := $(ARCH_DIR)/main.c \
$(ARCH_DIR)/devices.c \
$(SRC_DIR)/tools/parser.c \
$(SRC_DIR)/tools/lexer.c \
$(SRC_DIR)/tools/assembler.c
$(SRC_DIR)/tools/assembler.c\
$(SRC_DIR)/tools/compiler.c
endif
# --- OBJECT FILES ---

View File

@ -58,23 +58,16 @@ The Undâr compiler will be written in Sċieppan, as well as core VM tests.
#+BEGIN_SRC lisp
((code
(label main
(load-immediate $1 &hello-str) ; load hello string ptr
(call &pln ($1) nil)
(halt)) ; done
(label pln
(load-immediate $1 &terminal-namespace) ; get terminal device
(load-immediate $11 0)
(syscall OPEN $1 $1 $11)
(load-immediate $3 &new-line)
(string-length $2 $0)
(syscall WRITE $1 $0 $2)
(string-length $4 $3)
(syscall WRITE $1 $3 $4)
(return nil)))
(ldi $0 &terminal-namespace) ; get terminal device
(ldi $1 0)
(syscall OPEN $0 $0 $1)
(ldi $1 &hello-str) ; load hello string ptr
(strlen $2 $1)
(syscall WRITE $0 $1 $2)
(halt 0)))
(data
(label terminal-namespace "/dev/term/0")
(label new-line "\n")
(label hello-str "nuqneH 'u'?")))
(label hello-str "nuqneH 'u'?\n")))
#+END_SRC
#+BEGIN_SRC sh
@ -92,24 +85,24 @@ heap allocations using the internal malloc opcode push pointers within this fram
#+BEGIN_SRC lisp
((code
(label main
(load-immediate $0 &terminal-namespace) ; get terminal device
(load-immediate $11 0)
(ldi $0 &terminal-namespace) ; get terminal device
(ldi $11 0)
(syscall OPEN $0 $0 $11)
(load-immediate $1 &help) ; print help message
(call &pln ($0 $1) nil)
(ldi $1 &help) ; print help message
(fcall &pln ($0 $1) nil)
(load-immediate $1 32) ; read in a string of max 32 char length
(ldi $1 32) ; read in a string of max 32 char length
(malloc $4 $1) ; allocate memory for the string
(syscall READ $0 $4 $1) ; read the string
(call &pln ($0 $4) nil) ; print the string
(fcall &pln ($0 $4) nil) ; print the string
(halt))
(label pln
(load-immediate $3 &new-line)
(string-length $2 $1)
(ldi $3 &new-line)
(strlen $2 $1)
(syscall WRITE $0 $1 $2)
(string-length $4 $3)
(strlen $4 $3)
(syscall WRITE $0 $3 $4)
(return nil)))
(data

View File

@ -3,4 +3,4 @@
(return n))
(return (+ (fib (- n 2)) (fib (- n 1)))))
(print (fib 35))
(print (fib 36))

View File

@ -3,6 +3,6 @@ function fib(n)
return fib(n-1) + fib(n-2)
end
local result = fib(35)
local result = fib(36)
print(result)

View File

@ -7,6 +7,6 @@ sub fib {
return fib($n-1) + fib($n-2);
}
my $result = fib(35);
my $result = fib(36);
print "$result\n";

View File

@ -3,5 +3,5 @@ def fib(n):
return n
return fib(n-1) + fib(n-2)
result = fib(35)
result = fib(36)
print(result)

View File

@ -3,5 +3,5 @@ fn fib(n) {
return fib(n - 2) + fib(n - 1);
}
let result = fib(35);
let result = fib(36);
print result;

View File

@ -1,8 +1,7 @@
#include "devices.h"
#include <stdio.h>
#include <string.h>
#include <emscripten.h>
#include <emscripten/html5.h>
#include <unistd.h>
i32 console_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size) {
USED(mode);
@ -141,10 +140,14 @@ i32 mouse_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size) {
}
i32 mouse_read(void *data, u8 *buffer, u32 size) {
MouseDeviceData *mouse_data = (MouseDeviceData *)data;
USED(data);
USED(buffer);
USED(size);
return -1;
}
if (size < 12)
return -1;
i32 mouse_refresh(void *data, u8 *buffer) {
MouseDeviceData *mouse_data = (MouseDeviceData *)data;
u8 *info = (u8 *)buffer;
memcpy(&info[4], &mouse_data->x, sizeof(u32));

View File

@ -26,16 +26,13 @@ typedef struct mouse_device_data_s {
u8 btn2;
u8 btn3;
u8 btn4;
u32 size;
} MouseDeviceData;
/* Keyboard device data */
typedef struct keyboard_device_data_s {
u32 handle;
const u8 *keys;
i32 key_count;
u32 pos;
u32 size;
const u8 *keys;
} KeyboardDeviceData;
/* Console device data */
@ -52,6 +49,7 @@ i32 screen_ioctl(void *data, u32 cmd, const u8 *buffer);
i32 mouse_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size);
i32 mouse_read(void *data, u8 *buffer, u32 size);
i32 mouse_refresh(void *data, u8 *buffer);
i32 mouse_write(void *data, const u8 *buffer, u32 size);
i32 mouse_close(void *data);

View File

@ -18,7 +18,8 @@ static DeviceOps mouse_ops = {.open = mouse_open,
.read = mouse_read,
.write = mouse_write,
.close = mouse_close,
.ioctl = nil};
.ioctl = nil,
.refresh = mouse_refresh};
static DeviceOps console_device_ops = {
.open = console_open,
@ -177,13 +178,12 @@ int main(int argc, char **argv) {
mouse_data.btn2 = 0;
mouse_data.btn3 = 0;
mouse_data.btn4 = 0;
mouse_data.size = 16;
// Register devices
vm_register_device(&vm, "/dev/screen/0", "screen", &screen_data,
&screen_ops, 16 + screen_data.buffer_size);
vm_register_device(&vm, "/dev/mouse/0", "mouse", &mouse_data, &mouse_ops,
mouse_data.size);
16);
vm_register_device(&vm, "/dev/term/0", "terminal", &console_data,
&console_device_ops, 4);

View File

@ -1,11 +1,12 @@
#include "../../tools/assembler.h"
#include "../../tools/lexer.h"
#include "../../tools/compiler.h"
#include "../../tools/parser.h"
#include "../../vm/vm.h"
#include "devices.h"
#include <SDL2/SDL.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -280,130 +281,130 @@ const char *opcode_to_string(Opcode op) {
static const char *names[] = {
[OP_HALT] = "halt",
[OP_JMP] = "jump",
[OP_JMPF] = "jump-if-flag",
[OP_CALL] = "call",
[OP_RETURN] = "return",
[OP_JMPF] = "jmpf",
[OP_FCALL] = "fcall",
[OP_FRETURN] = "return",
/* Immediate loads (only 32-bit variant needed) */
[OP_LOAD_IMM] = "load-immediate",
[OP_LOAD_IMM] = "ldi",
/* Register-indirect loads */
[OP_LOAD_IND_8] = "load-indirect-8",
[OP_LOAD_IND_16] = "load-indirect-16",
[OP_LOAD_IND_32] = "load-indirect-32",
[OP_LOAD_IND_8] = "ld8",
[OP_LOAD_IND_16] = "ld16",
[OP_LOAD_IND_32] = "ld32",
/* Absolute address loads */
[OP_LOAD_ABS_8] = "load-absolute-8",
[OP_LOAD_ABS_16] = "load-absolute-16",
[OP_LOAD_ABS_32] = "load-absolute-32",
[OP_LOAD_ABS_8] = "lda8",
[OP_LOAD_ABS_16] = "lda16",
[OP_LOAD_ABS_32] = "lda32",
/* Base+offset loads */
[OP_LOAD_OFF_8] = "load-offset-8",
[OP_LOAD_OFF_16] = "load-offset-16",
[OP_LOAD_OFF_32] = "load-offset-32",
[OP_LOAD_OFF_8] = "ldo8",
[OP_LOAD_OFF_16] = "ldo16",
[OP_LOAD_OFF_32] = "ldo32",
/* Absolute address stores */
[OP_STORE_ABS_8] = "store-absolute-8",
[OP_STORE_ABS_16] = "store-absolute-16",
[OP_STORE_ABS_32] = "store-absolute-32",
[OP_STORE_ABS_8] = "sta8",
[OP_STORE_ABS_16] = "sta16",
[OP_STORE_ABS_32] = "sta32",
/* Register-indirect stores */
[OP_STORE_IND_8] = "store-indirect-8",
[OP_STORE_IND_16] = "store-indirect-16",
[OP_STORE_IND_32] = "store-indirect-32",
[OP_STORE_IND_8] = "sti8",
[OP_STORE_IND_16] = "sti16",
[OP_STORE_IND_32] = "sti32",
/* Base+offset stores */
[OP_STORE_OFF_8] = "store-offset-8",
[OP_STORE_OFF_16] = "store-offset-16",
[OP_STORE_OFF_32] = "store-offset-32",
[OP_STORE_OFF_8] = "sto8",
[OP_STORE_OFF_16] = "sto16",
[OP_STORE_OFF_32] = "sto32",
/* Memory operations */
[OP_MALLOC] = "malloc",
[OP_MEMSET_8] = "memset-8",
[OP_MEMSET_16] = "memset-16",
[OP_MEMSET_32] = "memset-32",
[OP_MEMSET_8] = "set8",
[OP_MEMSET_16] = "set16",
[OP_MEMSET_32] = "set32",
/* Register operations */
[OP_REG_MOV] = "register-move",
[OP_REG_MOV] = "mov",
[OP_SYSCALL] = "syscall",
/* Bit operations */
[OP_BIT_SHIFT_LEFT] = "bit-shift-left",
[OP_BIT_SHIFT_RIGHT] = "bit-shift-right",
[OP_BIT_SHIFT_R_EXT] = "bit-shift-r-ext",
[OP_BAND] = "bit-and",
[OP_BOR] = "bit-or",
[OP_BXOR] = "bit-xor",
[OP_BIT_SHIFT_LEFT] = "sll",
[OP_BIT_SHIFT_RIGHT] = "srl",
[OP_BIT_SHIFT_R_EXT] = "sre",
[OP_BAND] = "and",
[OP_BOR] = "or",
[OP_BXOR] = "xor",
/* Integer arithmetic */
[OP_ADD_INT] = "add-int",
[OP_SUB_INT] = "sub-int",
[OP_MUL_INT] = "mul-int",
[OP_DIV_INT] = "div-int",
[OP_ABS_INT] = "abs-int", // ← NEW
[OP_NEG_INT] = "neg-int", // ← NEW
[OP_ADD_INT] = "addi",
[OP_SUB_INT] = "subi",
[OP_MUL_INT] = "muli",
[OP_DIV_INT] = "divi",
[OP_ABS_INT] = "absi", // ← NEW
[OP_NEG_INT] = "negi", // ← NEW
/* Natural number arithmetic */
[OP_ADD_NAT] = "add-nat",
[OP_SUB_NAT] = "sub-nat",
[OP_MUL_NAT] = "mul-nat",
[OP_DIV_NAT] = "div-nat",
[OP_ABS_NAT] = "abs-nat", // ← NEW
[OP_NEG_NAT] = "neg-nat", // ← NEW
[OP_ADD_NAT] = "addn",
[OP_SUB_NAT] = "subn",
[OP_MUL_NAT] = "muln",
[OP_DIV_NAT] = "divn",
[OP_ABS_NAT] = "absn", // ← NEW
[OP_NEG_NAT] = "negn", // ← NEW
/* Floating point operations */
[OP_ADD_REAL] = "add-real",
[OP_SUB_REAL] = "sub-real",
[OP_MUL_REAL] = "mul-real",
[OP_DIV_REAL] = "div-real",
[OP_ABS_REAL] = "abs-real", // ← NEW
[OP_NEG_REAL] = "neg-real", // ← NEW
[OP_ADD_REAL] = "addr",
[OP_SUB_REAL] = "subr",
[OP_MUL_REAL] = "mulr",
[OP_DIV_REAL] = "divr",
[OP_ABS_REAL] = "absr", // ← NEW
[OP_NEG_REAL] = "negr", // ← NEW
/* Type conversions */
[OP_INT_TO_REAL] = "int-to-real",
[OP_NAT_TO_REAL] = "nat-to-real",
[OP_REAL_TO_INT] = "real-to-int",
[OP_REAL_TO_NAT] = "real-to-nat",
[OP_INT_TO_REAL] = "itor",
[OP_NAT_TO_REAL] = "ntor",
[OP_REAL_TO_INT] = "rtoi",
[OP_REAL_TO_NAT] = "rton",
/* Integer comparisons */
[OP_JEQ_INT] = "jump-eq-int",
[OP_JNEQ_INT] = "jump-neq-int",
[OP_JGT_INT] = "jump-gt-int",
[OP_JLT_INT] = "jump-lt-int",
[OP_JLE_INT] = "jump-le-int",
[OP_JGE_INT] = "jump-ge-int",
[OP_JEQ_INT] = "jeqi",
[OP_JNEQ_INT] = "jneqi",
[OP_JGT_INT] = "jgti",
[OP_JLT_INT] = "jlti",
[OP_JLE_INT] = "jlei",
[OP_JGE_INT] = "jgei",
/* Natural number comparisons */
[OP_JEQ_NAT] = "jump-eq-nat",
[OP_JNEQ_NAT] = "jump-neq-nat",
[OP_JGT_NAT] = "jump-gt-nat",
[OP_JLT_NAT] = "jump-lt-nat",
[OP_JLE_NAT] = "jump-le-nat",
[OP_JGE_NAT] = "jump-ge-nat",
[OP_JEQ_NAT] = "jeqn",
[OP_JNEQ_NAT] = "jneqn",
[OP_JGT_NAT] = "jgtn",
[OP_JLT_NAT] = "jltn",
[OP_JLE_NAT] = "jlen",
[OP_JGE_NAT] = "jgen",
/* Floating point comparisons */
[OP_JEQ_REAL] = "jump-eq-real",
[OP_JNEQ_REAL] = "jump-neq-real",
[OP_JGE_REAL] = "jump-ge-real",
[OP_JGT_REAL] = "jump-gt-real",
[OP_JLT_REAL] = "jump-lt-real",
[OP_JLE_REAL] = "jump-le-real",
[OP_JEQ_REAL] = "jeqr",
[OP_JNEQ_REAL] = "jneqr",
[OP_JGE_REAL] = "jger",
[OP_JGT_REAL] = "jgtr",
[OP_JLT_REAL] = "jltr",
[OP_JLE_REAL] = "jler",
/* String operations */
[OP_STRLEN] = "string-length",
[OP_STREQ] = "string-eq",
[OP_STRCAT] = "string-concat",
[OP_STR_GET_CHAR] = "string-get-char",
[OP_STR_FIND_CHAR] = "string-find-char",
[OP_STR_SLICE] = "string-slice",
[OP_STRLEN] = "strlen",
[OP_STREQ] = "streq",
[OP_STRCAT] = "strcat",
[OP_STR_GET_CHAR] = "getch",
[OP_STR_FIND_CHAR] = "findch",
[OP_STR_SLICE] = "strcut",
/* String conversions */
[OP_INT_TO_STRING] = "int-to-string",
[OP_NAT_TO_STRING] = "nat-to-string",
[OP_REAL_TO_STRING] = "real-to-string",
[OP_STRING_TO_INT] = "string-to-int",
[OP_STRING_TO_NAT] = "string-to-nat",
[OP_STRING_TO_REAL] = "string-to-real"};
[OP_INT_TO_STRING] = "itos",
[OP_NAT_TO_STRING] = "ntos",
[OP_REAL_TO_STRING] = "rtos",
[OP_STRING_TO_INT] = "stoi",
[OP_STRING_TO_NAT] = "ston",
[OP_STRING_TO_REAL] = "stor"};
if (op < 0 || op >= (int)(sizeof(names) / sizeof(names[0]))) {
return "<invalid-opcode>";

200
src/tools/compiler.c Normal file
View File

@ -0,0 +1,200 @@
#include "compiler.h"
#include "lexer.h"
#include <stdarg.h>
#include <stdio.h>
//typedef struct {
// Token current;
// Token previous;
// bool hadError;
// bool panicMode;
//} Parser;
//
//typedef enum {
// PREC_NONE,
// PREC_ASSIGNMENT, /* = */
// PREC_OR, /* or */
// PREC_AND, /* and */
// PREC_EQUALITY, /* == != */
// PREC_COMPARISON, /* < > <= >= */
// PREC_TERM, /* + - */
// PREC_FACTOR, /* * / */
// PREC_UNARY, /* not */
// PREC_CALL, /* . () */
// PREC_PRIMARY
//} Precedence;
//
//typedef void (*ParseFn)(char *program);
//
//typedef struct {
// ParseFn prefix;
// ParseFn infix;
// Precedence precedence;
//} ParseRule;
//
//typedef struct {
// i8 rp; // Next free register
//} Compiler;
//
//Parser parser;
//
//const char *internalErrorMsg =
// "FLAGRANT COMPILER ERROR\n\nCompiler over.\nBug = Very Yes.";
//
//void errorAt(Token *token, const char *message) {
// if (parser.panicMode)
// return;
// parser.panicMode = true;
// fprintf(stderr, "[line %d] Error", token->line);
//
// if (token->type == TOKEN_EOF) {
// fprintf(stderr, " at end");
// } else if (token->type == TOKEN_ERROR) {
// } else {
// fprintf(stderr, " at '%.*s'", token->length, token->start);
// }
//
// fprintf(stderr, ": %s\n", message);
// parser.hadError = true;
//}
//
//void error(const char *message) { errorAt(&parser.previous, message); }
//
//void errorAtCurrent(const char *message) { errorAt(&parser.current, message); }
//
//void advance() {
// parser.previous = parser.current;
//
// for (;;) {
// parser.current = nextToken();
// if (parser.current.type != TOKEN_ERROR)
// break;
//
// errorAtCurrent(parser.current.start);
// }
//}
//
//void consume(TokenType type, const char *message) {
// if (parser.current.type == type) {
// advance();
// return;
// }
//
// errorAtCurrent(message);
//}
//
//static int allocateRegister(Compiler *c) {
// char buffer[38];
// if (c->rp > 28) {
// sprintf(buffer, "Out of registers (used %d, max 28)", c->rp);
// error(buffer);
// return -1;
// }
//
// return c->rp++;
//}
//static void freeRegister(Compiler *c, u8 reg) {
// if (reg == c->rp - 1) {
// c->rp--;
// }
//}
//void emit_byte(VM *vm, u8 byte) { vm->code[vm->cp++] = byte; }
//
//void emit_u32(VM *vm, u32 value) {
// write_u32(vm, code, vm->cp, value);
// vm->cp += 4;
//}
//
//void emit_opcode(VM *vm, Opcode op) { emit_byte(vm, op); }
//
//static bool check(TokenType type) { return parser.current.type == type; }
//
//static bool match(TokenType type) {
// if (!check(type))
// return false;
// advance();
// return true;
//}
//
//static void expression(Compiler *c, VM *vm) {
// USED(c);
// USED(vm);
//}
//
//void number(Compiler *c, VM *vm) {
// emit_opcode(vm, OP_LOAD_IMM);
// int reg = allocateRegister(c);
// if (reg < 0)
// return;
// emit_byte(vm, reg);
//
// switch (parser.previous.type) {
// case TOKEN_INT_LITERAL: {
// char *endptr;
// i32 value = (i32)strtol(parser.previous.start, &endptr, 10);
// emit_u32(vm, value);
// return;
// }
// case TOKEN_UINT_LITERAL: {
// long value = atol(parser.previous.start);
// emit_u32(vm, value);
// return;
// }
// case TOKEN_FLOAT_LITERAL: {
// float value = atof(parser.previous.start);
// fixed_t fvalue = float_to_fixed(value);
// emit_u32(vm, fvalue);
// return;
// }
// default:
// return; // Unreachable.
// }
//
// errorAtCurrent("Invalid number format");
//}
//
//static void unary(Compiler *c, VM *vm) {
// TokenType operatorType = parser.previous.type;
//
// // Compile the operand.
// expression(c, vm);
//
// // Emit the operator instruction.
// switch (operatorType) {
// default:
// return; // Unreachable.
// }
//}
//
//static void emitHalt(Compiler *c, VM *vm) {
// emit_opcode(vm, OP_HALT);
// advance();
// number(c, vm);
//}
//
//static void endCompiler(Compiler *c, VM *vm) { emitHalt(c, vm); }
//
//static void grouping(Compiler *c, VM *vm) {
// expression(c, vm);
// consume(TOKEN_RPAREN, "Expect ')' after expression.");
//}
bool compile(const char *source, VM *vm) {
USED(source);
USED(vm);
//initLexer(source);
//
//parser.hadError = false;
//parser.panicMode = false;
//
//Compiler compiler;
//advance();
//expression(&compiler, vm);
//consume(TOKEN_EOF, "Expect end of expression.");
//endCompiler(&compiler, vm);
//
//return parser.hadError;
return false;
}

38
src/tools/compiler.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef UNDAR_COMPILER_H
#define UNDAR_COMPILER_H
#include "../vm/common.h"
#include "../vm/vm.h"
#include "../vm/fixed.h"
#include "lexer.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct field_s {
char* name; // "handle"
TokenType type; // TOKEN_TYPE_NAT
u32 offset; // 4 (for first field in heap object)
u32 size; // 4 (bytes for nat)
} Field;
typedef struct plex_def_s {
char* name;
u32 field_count;
u32 logical_size; // Data size (e.g., 12 for Vec3)
u32 physical_size; // Total allocation (logical + 4)
Field *fields; // All offsets are PHYSICAL
} PlexDef;
typedef struct array_def_s {
TokenType type;
u32 length;
u32 logical_size; // length * element_size
u32 physical_size; // logical_size + 4
} ArrayDef;
bool compile(const char *source, VM *vm);
#endif

View File

@ -10,6 +10,7 @@ typedef uint16_t u16;
typedef int16_t i16;
typedef uint32_t u32;
typedef int32_t i32;
typedef float f32;
#define true 1
#define false 0

181
src/vm/fixed.c Normal file
View File

@ -0,0 +1,181 @@
/* fixed.c - Q16.16 Fixed-Point Math Implementation */
#include "fixed.h"
/* Conversion functions */
fixed_t int_to_fixed(i32 i) { return i << 16; }
i32 fixed_to_int(fixed_t f) { return f >> 16; }
fixed_t float_to_fixed(f32 f) { return (fixed_t)(f * 65536.0f); }
f32 fixed_to_float(fixed_t f) { return (f32)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 */
i32 a_hi = a >> 16;
u32 a_lo = (u32)a & 0xFFFFU;
i32 b_hi = b >> 16;
u32 b_lo = (u32)b & 0xFFFFU;
/* Compute partial products */
i32 p0 = (i32)(a_lo * b_lo) >> 16; /* Low * Low */
i32 p1 = a_hi * (i32)b_lo; /* High * Low */
i32 p2 = (i32)a_lo * b_hi; /* Low * High */
i32 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) {
int negative;
u32 ua, ub, quotient, remainder;
int i;
if (b == 0)
return 0; /* Handle division by zero */
/* Determine sign */
negative = ((a < 0) ^ (b < 0));
/* Work with absolute values */
ua = (a < 0) ? -a : a;
ub = (b < 0) ? -b : b;
/* Perform division using long division in base 2^16 */
quotient = 0;
remainder = 0;
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 ? -(i32)quotient : (i32)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) {
fixed_t x, prev;
if (f <= 0)
return 0;
x = f;
/* 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) {
fixed_t result, term, f_squared;
int i;
/* 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! + ... */
result = f;
term = f;
f_squared = fixed_mul(f, f);
/* Calculate first few terms for reasonable precision */
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;
}

53
src/vm/fixed.h Normal file
View File

@ -0,0 +1,53 @@
#ifndef FIXED_H
#define FIXED_H
#include "common.h"
/* Q16.16 fixed-point type */
typedef i32 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(i32 i);
i32 fixed_to_int(fixed_t f);
fixed_t float_to_fixed(f32 f);
f32 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

@ -1,7 +1,8 @@
#include "vm.h"
#include "device.h"
#include "opcodes.h"
#include "fixed.h"
#include "libc.h"
#include "opcodes.h"
#define COMPARE_AND_JUMP(type, op) \
do { \
@ -101,12 +102,10 @@ bool step_vm(VM *vm) {
Frame *child;
u32 jmp, heap_mask, i;
/* Read call parameters */
jmp = read_u32(vm, code, vm->pc);
vm->pc += 4;
N = vm->code[vm->pc++];
/* Read arguments */
for (i = 0; i < N; i++) {
args[i] = vm->code[vm->pc++];
}
@ -114,7 +113,6 @@ bool step_vm(VM *vm) {
return_reg = vm->code[vm->pc++];
frame->return_reg = return_reg;
/* Stack and frame checks */
if (vm->sp >= STACK_SIZE)
return false;
vm->stack[vm->sp++] = vm->pc;
@ -123,14 +121,12 @@ bool step_vm(VM *vm) {
return false;
vm->fp++;
/* Setup child frame */
child = &vm->frames[vm->fp];
child->start = vm->mp;
child->end = vm->mp;
child->return_reg = 0;
child->heap_mask = 0;
/* Optimized register copy with bitmask for heap status */
heap_mask = 0;
for (i = 0; i < N; i++) {
src_reg = args[i];
@ -185,11 +181,9 @@ bool step_vm(VM *vm) {
if (parent->end + size + 4 > MEMORY_SIZE) {
return false;
}
*(u32 *)(vm->memory + new_ptr) = size;
memcopy(vm->memory + new_ptr + 4, vm->memory + ptr + 4, size);
parent->end += size + 4;
parent->registers[parent->return_reg] = new_ptr;
parent->heap_mask |= (1 << parent->return_reg);
} else {
@ -198,7 +192,6 @@ bool step_vm(VM *vm) {
}
}
/* Always handle frame cleanup */
vm->pc = vm->stack[--vm->sp];
vm->mp = child->start;
vm->fp--;
@ -603,7 +596,7 @@ bool step_vm(VM *vm) {
device_ptr = frame->registers[device_reg]; /* device pointer */
buffer_ptr = frame->registers[buffer_reg];
size = frame->registers[size_reg]; /* size */
size = frame->registers[size_reg]; /* size */
handle = vm->memory[device_ptr + 4]; /* get device handle */
dev = &vm->devices[handle];
@ -624,7 +617,7 @@ bool step_vm(VM *vm) {
vm->pc++;
device_ptr = frame->registers[device_reg]; /* device pointer */
handle = vm->memory[device_ptr + 4]; /* get device handle */
handle = vm->memory[device_ptr + 4]; /* get device handle */
dev = &vm->devices[handle];
if (dev && dev->ops->refresh) {
vm->flag = dev->ops->refresh(dev->data, &vm->memory[device_ptr + 4]);
@ -635,7 +628,6 @@ bool step_vm(VM *vm) {
return true;
}
case SYSCALL_DEVICE_WRITE: {
Device *dev;
u32 handle, buffer_ptr, size, device_ptr;
@ -743,28 +735,28 @@ bool step_vm(VM *vm) {
case OP_DIV_INT:
MATH_OP(i32, /);
case OP_ABS_INT: {
dest = read_u8(vm, code, vm->pc);
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
dest = read_u8(vm, code, vm->pc);
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
value = frame->registers[src1];
if (value < 0) {
value = -value;
}
value = frame->registers[src1];
if (value < 0) {
value = -value;
}
frame->registers[dest] = value;
return true;
frame->registers[dest] = value;
return true;
}
case OP_NEG_INT: {
dest = read_u8(vm, code, vm->pc);
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
dest = read_u8(vm, code, vm->pc);
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
value = frame->registers[src1];
frame->registers[dest] = -value;
return true;
value = frame->registers[src1];
frame->registers[dest] = -value;
return true;
}
case OP_ADD_NAT:
MATH_OP(u32, +);
@ -782,7 +774,7 @@ bool step_vm(VM *vm) {
src2 = read_u8(vm, code, vm->pc);
vm->pc++;
frame->registers[dest] =
(frame->registers[src1] * frame->registers[src2]) >> 16;
fixed_mul(frame->registers[src1], frame->registers[src2]);
return true;
}
@ -794,7 +786,7 @@ bool step_vm(VM *vm) {
src2 = read_u8(vm, code, vm->pc);
vm->pc++;
frame->registers[dest] =
(frame->registers[src1] << 16) / frame->registers[src2];
fixed_div(frame->registers[src1], frame->registers[src2]);
return true;
}
@ -805,7 +797,8 @@ bool step_vm(VM *vm) {
vm->pc++;
src2 = read_u8(vm, code, vm->pc);
vm->pc++;
frame->registers[dest] = frame->registers[src1] + frame->registers[src2];
frame->registers[dest] =
fixed_add(frame->registers[src1], frame->registers[src2]);
return true;
}
@ -816,7 +809,8 @@ bool step_vm(VM *vm) {
vm->pc++;
src2 = read_u8(vm, code, vm->pc);
vm->pc++;
frame->registers[dest] = frame->registers[src1] - frame->registers[src2];
frame->registers[dest] =
fixed_sub(frame->registers[src1], frame->registers[src2]);
return true;
}
case OP_REAL_TO_INT: {
@ -826,11 +820,7 @@ bool step_vm(VM *vm) {
vm->pc++;
value = frame->registers[src1];
if (value >= 0) {
frame->registers[dest] = value >> 16;
} else {
frame->registers[dest] = -((-value) >> 16);
}
frame->registers[dest] = fixed_to_int(value);
return true;
}
@ -839,7 +829,7 @@ bool step_vm(VM *vm) {
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
frame->registers[dest] = (frame->registers[src1] << 16);
frame->registers[dest] = int_to_fixed(frame->registers[src1]);
return true;
}
case OP_REAL_TO_NAT: {
@ -848,11 +838,7 @@ bool step_vm(VM *vm) {
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
value = frame->registers[src1];
if (value < 0) {
frame->registers[dest] = 0;
} else {
frame->registers[dest] = AS_NAT(value >> 16);
}
frame->registers[dest] = fixed_to_int(value);
return true;
}
case OP_NAT_TO_REAL: {
@ -860,7 +846,7 @@ bool step_vm(VM *vm) {
vm->pc++;
src1 = read_u8(vm, code, vm->pc);
vm->pc++;
frame->registers[dest] = AS_INT(frame->registers[src1] << 16);
frame->registers[dest] = int_to_fixed(frame->registers[src1]);
return true;
}
case OP_JEQ_NAT: {

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.