From c90f236ab329e909502fafe86ab5f080edfe5dbc Mon Sep 17 00:00:00 2001 From: zongor Date: Sun, 9 Nov 2025 13:22:46 -0800 Subject: [PATCH] Refactor and rename to align with new IR better --- Makefile | 12 +- README.org | 16 +- ROADMAP.org | 10 + src/arch/linux/main.c | 227 +-- src/tools/assembler/assembler.c | 1240 +---------------- src/tools/assembler/assembler.h | 22 +- src/tools/{ => assembler}/lexer.c | 2 +- src/tools/{ => assembler}/lexer.h | 0 src/tools/old_assembler/assembler.c | 1211 ++++++++++++++++ src/tools/old_assembler/assembler.h | 20 + .../{assembler => old_assembler}/parser.c | 0 .../{assembler => old_assembler}/parser.h | 0 src/vm/opcodes.h | 171 +-- src/vm/vm.c | 198 +-- test/add.asm.lisp | 2 +- test/add.ul.ir | 4 +- test/fib.asm.lisp | 2 +- test/fib.ul.ir | 4 +- test/hello.asm.lisp | 2 +- test/hello.ul.ir | 6 +- test/loop.asm.lisp | 2 +- test/loop.ul.ir | 8 +- test/malloc.asm.lisp | 2 +- test/malloc.ul.ir | 8 +- test/paint-bw.asm.lisp | 4 +- test/paint-bw.ul.ir | 2 +- test/paint.asm.lisp | 4 +- test/paint.ul.ir | 2 +- test/simple.asm.lisp | 2 +- test/simple.ul.ir | 4 +- test/window.asm.lisp | 2 +- test/window.ul.vuir | 26 +- 32 files changed, 1541 insertions(+), 1674 deletions(-) rename src/tools/{ => assembler}/lexer.c (99%) rename src/tools/{ => assembler}/lexer.h (100%) create mode 100644 src/tools/old_assembler/assembler.c create mode 100644 src/tools/old_assembler/assembler.h rename src/tools/{assembler => old_assembler}/parser.c (100%) rename src/tools/{assembler => old_assembler}/parser.h (100%) diff --git a/Makefile b/Makefile index 48b58fc..88100b7 100644 --- a/Makefile +++ b/Makefile @@ -86,13 +86,17 @@ VM_SOURCES := \ ifeq ($(BUILD_MODE), release) PLATFORM_SOURCE := $(ARCH_DIR)/main.c \ $(ARCH_DIR)/devices.c\ - $(SRC_DIR)/tools/assembler/parser.c \ - $(SRC_DIR)/tools/assembler/assembler.c + $(SRC_DIR)/tools/old_assembler/parser.c \ + $(SRC_DIR)/tools/old_assembler/assembler.c \ + $(SRC_DIR)/tools/assembler/lexer.c \ + $(SRC_DIR)/tools/assembler/assembler.c else PLATFORM_SOURCE := $(ARCH_DIR)/main.c \ $(ARCH_DIR)/devices.c \ - $(SRC_DIR)/tools/assembler/parser.c \ - $(SRC_DIR)/tools/assembler/assembler.c + $(SRC_DIR)/tools/old_assembler/parser.c \ + $(SRC_DIR)/tools/old_assembler/assembler.c\ + $(SRC_DIR)/tools/assembler/lexer.c \ + $(SRC_DIR)/tools/assembler/assembler.c endif # --- OBJECT FILES --- diff --git a/README.org b/README.org index 6e56f06..640f1fb 100644 --- a/README.org +++ b/README.org @@ -21,7 +21,7 @@ Undâr is a programming language for the purpose of creating 3D games and graphi It has an internal REPL that allows for quick development as well as the ability to dump the program to a binary rom for preserving that program/game/etc. -It runs on the =Reality Engine=, a VM written in freestanding C89, has a CISC like instruction format of one byte opcode and a variable byte operand. 32 general purpose registers. +It runs on the =Reality Engine=, a VM written in freestanding C89, has a CISC like instruction format of one byte opcode and a variable byte operand. 32 local variables per frame. * Philosophy @@ -58,7 +58,7 @@ You can view some examples in the =.ul.ir= files in =/test= function main () str hello is $0 - load_heap_immediate "nuqneH 'u'?" -> hello + malloc_immediate "nuqneH 'u'?" -> hello call pln hello exit 0 @@ -69,12 +69,12 @@ function pln (str message is $0) int nl_length is $4 int mode is $5 - load_heap_immediate "/dev/term/0" -> ts # get terminal device + malloc_immediate "/dev/term/0" -> ts # get terminal device load_immediate 0 -> mode syscall OPEN ts mode -> ts strlen message -> msg_length syscall WRITE ts message msg_length - load_heap_immediate "\n" -> nl + malloc_immediate "\n" -> nl strlen nl -> nl_length syscall WRITE ts nl nl_length return @@ -97,11 +97,11 @@ function main () int mode is $11 str term is $10 - load_heap_immediate "/dev/term/0" -> term + malloc_immediate "/dev/term/0" -> term load_immediate 0 -> mode syscall OPEN term mode -> term # Terminal term = open("/dev/term/0", 0); - load_heap_immediate "Enter a string:" -> $7 + malloc_immediate "Enter a string:" -> $7 string_length $7 -> $8 syscall WRITE term $7 $8 # print prompt @@ -120,12 +120,12 @@ function pln (str message is $0) str nl is $3 int nl_length is $4 - load_heap_immediate "/dev/term/0" -> ts + malloc_immediate "/dev/term/0" -> ts load_immediate 0 -> mode syscall OPEN ts mode -> ts # get terminal device strlen message -> msg_length syscall WRITE ts message msg_length - load_heap_immediate "\n" -> nl + malloc_immediate "\n" -> nl strlen nl -> nl_length syscall WRITE ts nl nl_length diff --git a/ROADMAP.org b/ROADMAP.org index 79f4043..d408d62 100644 --- a/ROADMAP.org +++ b/ROADMAP.org @@ -10,6 +10,16 @@ * Roadmap +** Fixes for devices + +Devices should be moved into the Tunnel concept + +Make it so that instead of returning the whole plex from the OPEN syscall we only return the handle + +We should remove the "refesh" options and make it so that "stat" + +Stat is the one that actually returns the plex with that info + ** Example: Hello world (=hello.ul=) *WIP syntax, not final implementation** diff --git a/src/arch/linux/main.c b/src/arch/linux/main.c index 17e8bd1..461daf9 100644 --- a/src/arch/linux/main.c +++ b/src/arch/linux/main.c @@ -1,5 +1,6 @@ +#include "../../tools/old_assembler/assembler.h" +#include "../../tools/old_assembler/parser.h" #include "../../tools/assembler/assembler.h" -#include "../../tools/assembler/parser.h" #include "../../vm/vm.h" #include "devices.h" #include @@ -52,7 +53,7 @@ bool saveVM(const char *filename, VM *vm) { return false; } - // Write VM state (registers and pointers) + // Write VM state (locals and pointers) if (fwrite(&vm->pc, sizeof(u32), 1, file) != 1 || fwrite(&vm->cp, sizeof(u32), 1, file) != 1 || fwrite(&vm->fp, sizeof(u32), 1, file) != 1 || @@ -90,7 +91,7 @@ bool loadVM(const char *filename, VM *vm) { return false; } - // Read VM state (registers and pointers) + // Read VM state (locals and pointers) if (fread(&vm->pc, sizeof(u32), 1, file) != 1 || fread(&vm->cp, sizeof(u32), 1, file) != 1 || fread(&vm->fp, sizeof(u32), 1, file) != 1 || @@ -145,7 +146,7 @@ bool compileAndSave(const char *source_file, const char *output_file, VM *vm) { source[read] = '\0'; fclose(f); - + assemble(vm, source); return true; } @@ -177,7 +178,7 @@ bool assembleAndSave(const char *source_file, const char *output_file, VM *vm) { printf("Parse failed.\n"); return false; } else { - assemble(vm, ast); + old_assemble(vm, ast); expr_free(ast); // If output file specified, save the VM @@ -192,216 +193,6 @@ bool assembleAndSave(const char *source_file, const char *output_file, VM *vm) { } } -void repl(VM *vm) { - USED(vm); - - char buffer[1024 * 10] = {0}; // Larger buffer for multi-line input - char line[1024]; - - for (;;) { - // Count current parentheses balance - i32 paren_balance = 0; - for (i32 i = 0; buffer[i]; i++) { - if (buffer[i] == '(') - paren_balance++; - else if (buffer[i] == ')') - paren_balance--; - } - - // Show appropriate prompt - if (paren_balance > 0) { - printf(".. "); // Continuation prompt when unbalanced - } else { - printf("> "); // Normal prompt when balanced - } - fflush(stdout); - - if (!fgets(line, sizeof(line), stdin)) { - printf("\n"); - break; - } - - // Append the new line to buffer - strncat(buffer, line, sizeof(buffer) - strlen(buffer) - 1); - - // Recalculate balance after adding new line - paren_balance = 0; - for (i32 i = 0; buffer[i]; i++) { - if (buffer[i] == '(') - paren_balance++; - else if (buffer[i] == ')') - paren_balance--; - } - - // Only parse when parentheses are balanced - if (paren_balance == 0) { - // Check if buffer has actual content (not just whitespace) - i32 has_content = 0; - for (i32 i = 0; buffer[i]; i++) { - if (!isspace(buffer[i])) { - has_content = 1; - break; - } - } - - if (has_content) { - ExprNode *ast = expr_parse(buffer, strlen(buffer)); - if (!ast) { - printf("Parse failed.\n"); - } else { - assemble(vm, ast); - while (step_vm(vm)) { - } - expr_free(ast); - } - } - - // Reset buffer for next input - buffer[0] = '\0'; - } - // If unbalanced, continue reading more lines - } - exit(vm->flag); -} -#ifdef ASM_DEBUG -const char *opcode_to_string(Opcode op) { - static const char *names[] = { - [OP_HALT] = "halt", - [OP_JMP] = "jump", - [OP_JMPF] = "jmpf", - [OP_FCALL] = "fcall", - [OP_FRETURN] = "return", - - /* Immediate loads (only 32-bit variant needed) */ - [OP_LOAD_IMM] = "ldi", - - /* Register-indirect loads */ - [OP_LOAD_IND_8] = "ld8", - [OP_LOAD_IND_16] = "ld16", - [OP_LOAD_IND_32] = "ld32", - - /* Absolute address loads */ - [OP_LOAD_ABS_8] = "lda8", - [OP_LOAD_ABS_16] = "lda16", - [OP_LOAD_ABS_32] = "lda32", - - /* Base+offset loads */ - [OP_LOAD_OFF_8] = "ldo8", - [OP_LOAD_OFF_16] = "ldo16", - [OP_LOAD_OFF_32] = "ldo32", - - /* Absolute address stores */ - [OP_STORE_ABS_8] = "sta8", - [OP_STORE_ABS_16] = "sta16", - [OP_STORE_ABS_32] = "sta32", - - /* Register-indirect stores */ - [OP_STORE_IND_8] = "sti8", - [OP_STORE_IND_16] = "sti16", - [OP_STORE_IND_32] = "sti32", - - /* Base+offset stores */ - [OP_STORE_OFF_8] = "sto8", - [OP_STORE_OFF_16] = "sto16", - [OP_STORE_OFF_32] = "sto32", - - /* Memory operations */ - [OP_MALLOC] = "malloc", - [OP_MEMSET_8] = "set8", - [OP_MEMSET_16] = "set16", - [OP_MEMSET_32] = "set32", - - /* Register operations */ - [OP_REG_MOV] = "mov", - [OP_SYSCALL] = "syscall", - - /* Bit operations */ - [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] = "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] = "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] = "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] = "itor", - [OP_NAT_TO_REAL] = "ntor", - [OP_REAL_TO_INT] = "rtoi", - [OP_REAL_TO_NAT] = "rton", - - /* Integer comparisons */ - [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] = "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] = "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] = "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] = "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 ""; - } - - const char *name = names[op]; - return name ? name : ""; -} -#endif - i32 main(i32 argc, char *argv[]) { bool dump_rom = false; char *input_file = nil; @@ -453,8 +244,7 @@ i32 main(i32 argc, char *argv[]) { } } } else { - // No input file - enter REPL mode - repl(&vm); + printf("usage: undar ..."); return 0; } @@ -567,9 +357,6 @@ i32 main(i32 argc, char *argv[]) { int cycles_this_frame = 0; int max_cycles_per_frame = 100; // Adjust this value while (cycles_this_frame < max_cycles_per_frame) { -#ifdef ASM_DEBUG - printf("| %s %d\n", opcode_to_string(vm.code[vm.pc]), vm.pc); -#endif if (!step_vm(&vm)) { running = false; break; diff --git a/src/tools/assembler/assembler.c b/src/tools/assembler/assembler.c index 49b6be4..93d8a19 100644 --- a/src/tools/assembler/assembler.c +++ b/src/tools/assembler/assembler.c @@ -1,1211 +1,55 @@ #include "assembler.h" -#include "parser.h" -typedef enum { SYMBOL_CODE, SYMBOL_DATA } SymbolType; +#include -typedef struct { +typedef struct field_s { + char* name; + TokenType type; + u32 offset; + u32 size; +} Field; + +typedef struct plex_def_s { + char* name; + u32 field_count; + u32 logical_size; + u32 physical_size; + Field *fields; +} PlexDef; + +typedef struct array_def_s { + TokenType type; + u32 length; + u32 logical_size; + u32 physical_size; // logical_size * type_size + 4 +} ArrayDef; + +typedef struct symbol_s { char *name; u32 address; - SymbolType type; - int size; // How much memory this symbol occupies - int is_constant; // 1 = constant, 0 = variable + TokenType type; + u32 logical_size; + u32 physical_size; // logical_size * type_size + 4 } Symbol; -typedef struct { +typedef struct symbol_tab_s { Symbol *symbols; int count; int capacity; } SymbolTable; -void symbol_table_init(SymbolTable *table) { - table->capacity = 32; - table->count = 0; - table->symbols = malloc(table->capacity * sizeof(Symbol)); -} - -void symbol_table_add(SymbolTable *table, const char *name, u32 address, - SymbolType type) { - // Check for duplicates - for (int i = 0; i < table->count; i++) { - if (strcmp(table->symbols[i].name, name) == 0) { - fprintf(stderr, "Error: Duplicate label '%s'\n", name); - exit(1); +void assemble(VM *vm, char *source) { + USED(vm); + initLexer(source); + Token token; + do { + token = nextToken(); + if (token.type == TOKEN_ERROR) { + printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start); + break; } - } - - if (table->count >= table->capacity) { - table->capacity *= 2; - table->symbols = realloc(table->symbols, table->capacity * sizeof(Symbol)); - } - - Symbol *sym = &table->symbols[table->count++]; - sym->name = strdup(name); - sym->address = address; - sym->type = type; - sym->size = 4; // Default size - sym->is_constant = 0; -} - -Symbol *symbol_table_lookup(SymbolTable *table, const char *name) { - for (int i = 0; i < table->count; i++) { - if (strcmp(table->symbols[i].name, name) == 0) { - return &table->symbols[i]; + if (token.type != TOKEN_EOF) { + printf("Line %d [%s]: %.*s\n", token.line, tokenTypeToString(token.type), + token.length, token.start); } - } - return NULL; -} - -u32 find_label_in_table(SymbolTable *table, const char *name) { - Symbol *sym = symbol_table_lookup(table, name); - if (!sym) { - fprintf(stderr, "Error: Undefined label '%s'\n", name); - exit(1); - } - return sym->address; -} - -int get_instruction_byte_size(ExprNode *node) { - const char *opname = node->token; - - // Return (1 + 1) - if (strcmp(opname, "return") == 0) { - return 2; // 1 byte opcode + 1 byte return register - } - - if (strcmp(opname, "neg-int") == 0 || - strcmp(opname, "abs-int") == 0 || - strcmp(opname, "neg-nat") == 0 || - strcmp(opname, "abs-nat") == 0 || - strcmp(opname, "neg-real") == 0 || - strcmp(opname, "abs-real") == 0 || - strcmp(opname, "int-to-string") == 0 || - strcmp(opname, "load-indirect-8") == 0 || - strcmp(opname, "nat-to-string") == 0 || - strcmp(opname, "load-indirect-16") == 0 || - strcmp(opname, "real-to-string") == 0 || - strcmp(opname, "load-indirect-32") == 0 || - strcmp(opname, "int-to-real") == 0 || - strcmp(opname, "store-indirect-8") == 0 || - strcmp(opname, "nat-to-real") == 0 || - strcmp(opname, "store-indirect-16") == 0 || - strcmp(opname, "real-to-int") == 0 || - strcmp(opname, "store-indirect-32") == 0 || - strcmp(opname, "real-to-nat") == 0 || strcmp(opname, "nat-to-int") == 0 || - strcmp(opname, "int-to-nat") == 0 || - strcmp(opname, "string-length") == 0 || - strcmp(opname, "store-absolute-32") == 0 || - strcmp(opname, "store-absolute-8") == 0 || - strcmp(opname, "store-absolute-16") == 0 || - strcmp(opname, "memset") == 0 || strcmp(opname, "memset") == 0 || - strcmp(opname, "memset-8") == 0 || strcmp(opname, "memset-16") == 0 || - strcmp(opname, "register-move") == 0 || strcmp(opname, "malloc") == 0) { - return 3; - } - - // Register-register-register opcodes (4 bytes: 1 + 3) - if (strcmp(opname, "add-int") == 0 || strcmp(opname, "sub-int") == 0 || - strcmp(opname, "mul-int") == 0 || strcmp(opname, "div-int") == 0 || - strcmp(opname, "add-nat") == 0 || strcmp(opname, "sub-nat") == 0 || - strcmp(opname, "mul-nat") == 0 || strcmp(opname, "div-nat") == 0 || - strcmp(opname, "add-real") == 0 || strcmp(opname, "sub-real") == 0 || - strcmp(opname, "bit-shift-left") == 0 || - strcmp(opname, "bit-shift-right") == 0 || - strcmp(opname, "bit-shift-r-ext") == 0 || - strcmp(opname, "bit-and") == 0 || strcmp(opname, "bit-or") == 0 || - strcmp(opname, "bit-xor") == 0 || strcmp(opname, "mul-real") == 0 || - strcmp(opname, "div-real") == 0) { - return 4; - } - - // (5 bytes: 1 + 4) - if (strcmp(opname, "halt") == 0 || strcmp(opname, "jump-if-flag") == 0 || - strcmp(opname, "jump") == 0) { - return 5; - } - - // Load, Load-immediate (6 bytes: 1 + 1 + 4) - if (strcmp(opname, "load-absolute-32") == 0 || - strcmp(opname, "load-immediate") == 0 || - strcmp(opname, "load-absolute-16") == 0 || - strcmp(opname, "load-absolute-8") == 0) { - return 6; - } - - // jump compare (7 bytes: 1 + 4 + 1 + 1) - if (strcmp(opname, "jump-eq-int") == 0 || - strcmp(opname, "jump-neq-int") == 0 || - strcmp(opname, "jump-gt-int") == 0 || - strcmp(opname, "jump-lt-int") == 0 || - strcmp(opname, "jump-le-int") == 0 || - strcmp(opname, "jump-ge-int") == 0 || - strcmp(opname, "jump-eq-nat") == 0 || - strcmp(opname, "jump-neq-nat") == 0 || - strcmp(opname, "jump-gt-nat") == 0 || - strcmp(opname, "jump-lt-nat") == 0 || - strcmp(opname, "jump-le-nat") == 0 || - strcmp(opname, "jump-ge-nat") == 0 || - strcmp(opname, "jump-eq-real") == 0 || - strcmp(opname, "jump-neq-real") == 0 || - strcmp(opname, "jump-gt-real") == 0 || - strcmp(opname, "jump-lt-real") == 0 || - strcmp(opname, "jump-le-real") == 0 || - strcmp(opname, "jump-ge-real") == 0 || - strcmp(opname, "store-offset-8") == 0 || - strcmp(opname, "store-offset-16") == 0 || - strcmp(opname, "store-offset-32") == 0 || - strcmp(opname, "load-offset-8") == 0 || - strcmp(opname, "load-offset-16") == 0 || - strcmp(opname, "load-offset-32") == 0) { - return 7; - } - - // Call (1 + 4 + 1 + args + 1) - if (strcmp(opname, "call") == 0) { - ExprNode *args_node = node->children[1]; - u32 args_count; - - if (strcmp(args_node->token, "nil") == 0) { - args_count = 0; - } else { - args_count = 1 + args_node->child_count; - } - - return 1 + 1 + 1 + 4 + args_count; - } - - // Syscall (1 + syscall_id (4) + args) - if (strcmp(opname, "syscall") == 0) { - return 1 + 4 + (node->child_count > 0 ? node->child_count - 1 : 0); - } - - fprintf(stderr, "Unknown opcode for sizing: %s\n", opname); - exit(-1); -} - -int calculate_instruction_size(ExprNode *node) { - if (node->child_count == 0) - return 0; - - return get_instruction_byte_size(node); -} - -void collect_symbols_in_node(SymbolTable *table, ExprNode *node, - u32 *current_addr, int depth) { - char indent[32] = ""; - for (int i = 0; i < depth; i++) - strcat(indent, " "); - -#ifdef ASM_DEBUG - printf("%s%d %s ", indent, *current_addr, node->token); -#endif - - if (strcmp(node->token, "label") == 0) { - if (node->child_count >= 1) { - const char *name = node->children[0]->token; -#ifdef ASM_DEBUG - printf(" %s -> %d\n", name, *current_addr); -#endif - symbol_table_add(table, name, *current_addr, SYMBOL_CODE); - } - - for (size_t i = 1; i < node->child_count; i++) { - collect_symbols_in_node(table, node->children[i], current_addr, - depth + 1); - } - } else { - int size = get_instruction_byte_size(node); - *current_addr += size; -#ifdef ASM_DEBUG - printf(" +%d bytes -> %d\n", size, *current_addr); -#endif - } -} - -void collect_symbols(SymbolTable *table, ExprNode *program) { - // First, collect all data labels (with placeholder address) - for (size_t i = 0; i < program->child_count; ++i) { - ExprNode *section = program->children[i]; - if (strcmp(section->token, "data") == 0) { - for (size_t j = 0; j < section->child_count; ++j) { - ExprNode *item = section->children[j]; - if (strcmp(item->token, "label") == 0 && item->child_count >= 2) { - const char *name = item->children[0]->token; - symbol_table_add(table, name, 0, SYMBOL_DATA); - } - } - } - } - - // Second, collect all code labels with proper nesting - u32 code_addr = 0; - for (size_t i = 0; i < program->child_count; ++i) { - ExprNode *section = program->children[i]; - if (strcmp(section->token, "code") == 0) { - for (size_t j = 0; j < section->child_count; ++j) { - collect_symbols_in_node(table, section->children[j], &code_addr, 0); - } - } - } -} - -u32 allocate_data(VM *vm, SymbolTable *table, const char *name, u32 size) { - u32 addr = vm->mp; - vm->mp += size; - vm->frames[vm->fp].end += size; - - // Update the symbol's address - Symbol *sym = symbol_table_lookup(table, name); - if (sym && sym->type == SYMBOL_DATA) { - sym->address = addr; - sym->size = size; - } - - return addr; -} - -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); } - -int parse_register(const char *reg_str) { - if (reg_str[0] != '$') - return -1; - return atoi(reg_str + 1); -} - -u32 resolve_symbol(SymbolTable *table, const char *ref) { - // Handle symbol references (e.g., &label) - if (ref[0] == '&') { - return find_label_in_table(table, ref + 1); - } - - // Handle fixed-point numbers (e.g., 0.5) - if (strchr(ref, '.')) { - return TO_FIXED(atof(ref)); - } - - // Handle hexadecimal literals (e.g., 0x7) - if (ref[0] == '0' && (ref[1] == 'x' || ref[1] == 'X')) { - char *endptr; - u32 value = (u32)strtoul(ref + 2, &endptr, 16); // Skip "0x" - - if (endptr == ref + 2 || *endptr != '\0') { - fprintf(stderr, "Invalid hex literal: %s\n", ref); - exit(1); - } - return value; - } - - // Handle decimal literals (e.g., 7) - char *endptr; - u32 value = (u32)strtoul(ref, &endptr, 10); - - if (endptr == ref || *endptr != '\0') { - fprintf(stderr, "Invalid decimal literal: %s\n", ref); - exit(1); - } - return value; -} - -static char *unwrap_string(const char *quoted_str) { - if (!quoted_str) - return NULL; - - size_t len = strlen(quoted_str); - if (len >= 2 && quoted_str[0] == '"' && quoted_str[len - 1] == '"') { - // Remove quotes and process escape sequences - const char *src = quoted_str + 1; - size_t src_len = len - 2; - - // First pass: calculate the actual length needed after escape processing - size_t actual_len = 0; - for (size_t i = 0; i < src_len; ++i) { - if (src[i] == '\\' && i + 1 < src_len) { - // Escape sequence - actual_len++; - i++; // Skip the next character - } else { - actual_len++; - } - } - - char *unwrapped = (char *)malloc(actual_len + 1); - size_t dst_idx = 0; - - // Second pass: process escape sequences - for (size_t i = 0; i < src_len; ++i) { - if (src[i] == '\\' && i + 1 < src_len) { - // Handle escape sequences - switch (src[i + 1]) { - case 'n': - unwrapped[dst_idx++] = '\n'; - break; - case 't': - unwrapped[dst_idx++] = '\t'; - break; - case 'r': - unwrapped[dst_idx++] = '\r'; - break; - case '\\': - unwrapped[dst_idx++] = '\\'; - break; - case '"': - unwrapped[dst_idx++] = '"'; - break; - case '\'': - unwrapped[dst_idx++] = '\''; - break; - default: - // Unknown escape, keep both characters - unwrapped[dst_idx++] = src[i]; - unwrapped[dst_idx++] = src[i + 1]; - break; - } - i++; // Skip the next character - } else { - unwrapped[dst_idx++] = src[i]; - } - } - unwrapped[dst_idx] = '\0'; - return unwrapped; - } - // Not quoted, return copy - return strdup(quoted_str); -} - -void process_data_block(VM *vm, SymbolTable *table, ExprNode *block) { - for (size_t i = 0; i < block->child_count; ++i) { - ExprNode *item = block->children[i]; - if (strcmp(item->token, "label") == 0 && item->child_count >= 2) { - const char *name = item->children[0]->token; - ExprNode *val = item->children[1]; - - if (val->child_count == 0) { - const char *token = val->token; - - // Case 1: String literal (enclosed in quotes) - if (token[0] == '"' && token[strlen(token) - 1] == '"') { - char *unwrapped = unwrap_string(token); - int len = strlen(unwrapped); - u32 addr = allocate_data(vm, table, name, len + 1 + 4); - - write_u32(vm, memory, addr, len); - for (int i = 0; i < len; i++) { - write_u8(vm, memory, addr + 4 + i, unwrapped[i]); - } - write_u8(vm, memory, addr + 4 + len, '\0'); - free(unwrapped); - } - // Case 2: Hexadecimal integer (0x...) - else if (token[0] == '0' && (token[1] == 'x' || token[1] == 'X')) { - char *endptr; - u32 value = (u32)strtoul(token + 2, &endptr, 16); - - if (endptr != token + strlen(token)) { - fprintf(stderr, "Invalid hex in data block: %s\n", token); - exit(1); - } - - u32 addr = allocate_data(vm, table, name, 4); - write_u32(vm, memory, addr, value); - } - // Case 3: Floating-point (has decimal point) - else if (strchr(token, '.')) { - float f = atof(token); - u32 addr = allocate_data(vm, table, name, 4); - write_u32(vm, memory, addr, TO_FIXED(f)); - } - // Case 4: Decimal integer - else { - char *endptr; - u32 value = (u32)strtoul(token, &endptr, 10); - - if (endptr != token + strlen(token)) { - fprintf(stderr, "Invalid decimal in data block: %s\n", token); - exit(1); - } - - u32 addr = allocate_data(vm, table, name, 4); - write_u32(vm, memory, addr, value); - //vm->mp += 4; - } - } else { - fprintf(stderr, "Unsupported data item\n"); - exit(1); - } - } - } -} - -void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) { - const char *opname = node->token; - if (strcmp(opname, "label") == 0) { - for (size_t i = 1; i < node->child_count; i++) { - process_code_expr(vm, table, node->children[i]); - } - } else if (strcmp(opname, "halt") == 0) { - emit_opcode(vm, OP_HALT); - u32 addr = resolve_symbol(table, node->children[0]->token); - emit_u32(vm, addr); - } else if (strcmp(opname, "jump") == 0) { - emit_opcode(vm, OP_JMP); - u32 addr = resolve_symbol(table, node->children[0]->token); - emit_u32(vm, addr); - } else if (strcmp(opname, "jump-if-flag") == 0) { - emit_opcode(vm, OP_JMPF); - u32 addr = resolve_symbol(table, node->children[0]->token); - emit_u32(vm, addr); - } else if (strcmp(opname, "call") == 0) { - emit_opcode(vm, OP_CALL); - - if (node->child_count < 3) { - fprintf(stderr, "Error: call requires (args) and return register\n"); - return; - } - - // Parse function address (first child) - u32 addr = resolve_symbol(table, node->children[0]->token); - if (addr == (u32)-1) { - fprintf(stderr, "Error: undefined symbol '%s'\n", - node->children[0]->token); - return; - } - emit_u32(vm, addr); - - // Parse argument list (second child) - ExprNode *args_node = node->children[1]; - u8 arg_count = 0; - - if (args_node->child_count > 0) { - // Multiple arguments case - arg_count = args_node->child_count + 1; // +1 for the token - } else { - // Single argument case - token is the argument - arg_count = (args_node->token[0] != '\0') ? 1 : 0; - } - emit_byte(vm, arg_count); - - // Emit arguments based on representation - if (arg_count > 0) { - // First argument is always the token - const char *reg_str = args_node->token; - int reg = parse_register(reg_str); - if (reg < 0) { - fprintf(stderr, "Error: invalid argument register '%s'\n", reg_str); - return; - } - emit_byte(vm, (u8)reg); - - // Emit children if present - for (size_t i = 0; i < args_node->child_count; i++) { - reg_str = args_node->children[i]->token; - reg = parse_register(reg_str); - if (reg < 0) { - fprintf(stderr, "Error: invalid argument register '%s'\n", reg_str); - return; - } - emit_byte(vm, (u8)reg); - } - } - // Parse return register (third child) - const char *return_reg_str = node->children[2]->token; - int return_reg = parse_register(return_reg_str); - - if (return_reg < 0) { - if (strcmp(return_reg_str, "nil") == 0) { - return_reg = 0xFF; - } else { - fprintf(stderr, "Error: invalid return register '%s'\n", - return_reg_str); - return; - } - } - emit_byte(vm, (u8)return_reg); - -} else if (strcmp(opname, "return") == 0) { - emit_opcode(vm, OP_RETURN); - - if (node->child_count != 1) { - fprintf(stderr, "Error: return requires exactly one argument\n"); - return; - } - - const char *reg_str = node->children[0]->token; - int reg = parse_register(reg_str); - - // Handle "nil" as special case (no return value) - if (reg < 0) { - if (strcmp(reg_str, "nil") == 0) { - reg = 0xFF; // Special value for "no return" - } else { - fprintf(stderr, "Error: invalid return register '%s'\n", reg_str); - return; - } - } - emit_byte(vm, (u8)reg); - } else if (strcmp(opname, "load-immediate") == 0) { - emit_opcode(vm, OP_LOAD_IMM); - int reg = parse_register(node->children[0]->token); - u32 addr = resolve_symbol(table, node->children[1]->token); - emit_byte(vm, reg); - emit_u32(vm, addr); - } else if (strcmp(opname, "load-absolute-8") == 0) { - emit_opcode(vm, OP_LOAD_ABS_8); - int dest = parse_register(node->children[0]->token); - u32 addr = resolve_symbol(table, node->children[1]->token); - emit_byte(vm, dest); - emit_u32(vm, addr); - } else if (strcmp(opname, "load-absolute-16") == 0) { - emit_opcode(vm, OP_LOAD_ABS_16); - int dest = parse_register(node->children[0]->token); - u32 addr = resolve_symbol(table, node->children[1]->token); - emit_byte(vm, dest); - emit_u32(vm, addr); - } else if (strcmp(opname, "load-absolute-32") == 0) { - emit_opcode(vm, OP_LOAD_ABS_32); - int dest = parse_register(node->children[0]->token); - u32 addr = resolve_symbol(table, node->children[1]->token); - emit_byte(vm, dest); - emit_u32(vm, addr); - } else if (strcmp(opname, "load-indirect-8") == 0) { - emit_opcode(vm, OP_LOAD_IND_8); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "load-indirect-16") == 0) { - emit_opcode(vm, OP_LOAD_IND_16); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "load-indirect-32") == 0) { - emit_opcode(vm, OP_LOAD_IND_32); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "malloc") == 0) { - emit_opcode(vm, OP_MALLOC); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "memset-8") == 0) { - emit_opcode(vm, OP_MEMSET_8); - int dest = parse_register(node->children[0]->token); - int value = parse_register(node->children[1]->token); - int count = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, value); - emit_byte(vm, count); - } else if (strcmp(opname, "memset-16") == 0) { - emit_opcode(vm, OP_MEMSET_16); - int dest = parse_register(node->children[0]->token); - int value = parse_register(node->children[1]->token); - int count = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, value); - emit_byte(vm, count); - } else if (strcmp(opname, "memset") == 0) { - emit_opcode(vm, OP_MEMSET_32); - int dest = parse_register(node->children[0]->token); - int value = parse_register(node->children[1]->token); - int count = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, value); - emit_byte(vm, count); - } else if (strcmp(opname, "store-absolute-8") == 0) { - emit_opcode(vm, OP_STORE_ABS_8); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "store-absolute-16") == 0) { - emit_opcode(vm, OP_STORE_ABS_16); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "store-absolute-32") == 0) { - emit_opcode(vm, OP_STORE_ABS_32); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "store-indirect-8") == 0) { - emit_opcode(vm, OP_STORE_IND_8); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "store-indirect-16") == 0) { - emit_opcode(vm, OP_STORE_IND_16); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "store-indirect-32") == 0) { - emit_opcode(vm, OP_STORE_IND_32); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "store-offset-8") == 0) { - emit_opcode(vm, OP_STORE_OFF_8); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - u32 addr = resolve_symbol(table, node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_u32(vm, addr); - } else if (strcmp(opname, "store-offset-16") == 0) { - emit_opcode(vm, OP_STORE_OFF_16); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - u32 addr = resolve_symbol(table, node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_u32(vm, addr); - } else if (strcmp(opname, "store-offset-32") == 0) { - emit_opcode(vm, OP_STORE_OFF_32); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - u32 addr = resolve_symbol(table, node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_u32(vm, addr); - } else if (strcmp(opname, "load-offset-8") == 0) { - emit_opcode(vm, OP_LOAD_OFF_8); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - u32 addr = resolve_symbol(table, node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_u32(vm, addr); - } else if (strcmp(opname, "load-offset-16") == 0) { - emit_opcode(vm, OP_LOAD_OFF_16); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - u32 addr = resolve_symbol(table, node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_u32(vm, addr); - } else if (strcmp(opname, "load-offset-32") == 0) { - emit_opcode(vm, OP_LOAD_OFF_32); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - u32 addr = resolve_symbol(table, node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_u32(vm, addr); - } else if (strcmp(opname, "register-move") == 0) { - emit_opcode(vm, OP_REG_MOV); - int dest = parse_register(node->children[0]->token); - int src = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src); - } else if (strcmp(opname, "syscall") == 0) { - emit_opcode(vm, OP_SYSCALL); - - // Parse syscall ID - u32 syscall_id = 0; - const char *syscall_name = node->children[0]->token; - if (strcmp(syscall_name, "EXIT") == 0) - syscall_id = SYSCALL_EXIT; - else if (strcmp(syscall_name, "OPEN") == 0) - syscall_id = SYSCALL_DEVICE_OPEN; - else if (strcmp(syscall_name, "READ") == 0) - syscall_id = SYSCALL_DEVICE_READ; - else if (strcmp(syscall_name, "WRITE") == 0) - syscall_id = SYSCALL_DEVICE_WRITE; - else if (strcmp(syscall_name, "CLOSE") == 0) - syscall_id = SYSCALL_DEVICE_CLOSE; - else if (strcmp(syscall_name, "IOCTL") == 0) - syscall_id = SYSCALL_DEVICE_IOCTL; - else if (strcmp(syscall_name, "REFRESH") == 0) - syscall_id = SYSCALL_DEVICE_REFRESH; - - emit_u32(vm, syscall_id); - - // Emit register arguments - for (size_t i = 1; i < node->child_count; ++i) { - int reg = parse_register(node->children[i]->token); - emit_byte(vm, reg); - } - } else if (strcmp(opname, "bit-shift-left") == 0) { - emit_opcode(vm, OP_BIT_SHIFT_LEFT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "bit-shift-right") == 0) { - emit_opcode(vm, OP_BIT_SHIFT_RIGHT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "bit-shift-r-ext") == 0) { - emit_opcode(vm, OP_BIT_SHIFT_R_EXT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "bit-and") == 0) { - emit_opcode(vm, OP_BAND); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "bit-or") == 0) { - emit_opcode(vm, OP_BOR); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "bit-xor") == 0) { - emit_opcode(vm, OP_BXOR); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "add-int") == 0) { - emit_opcode(vm, OP_ADD_INT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "sub-int") == 0) { - emit_opcode(vm, OP_SUB_INT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "mul-int") == 0) { - emit_opcode(vm, OP_MUL_INT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "div-int") == 0) { - emit_opcode(vm, OP_DIV_INT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "abs-int") == 0) { - emit_opcode(vm, OP_ABS_INT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "neg-int") == 0) { - emit_opcode(vm, OP_NEG_INT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "add-nat") == 0) { - emit_opcode(vm, OP_ADD_NAT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "sub-nat") == 0) { - emit_opcode(vm, OP_SUB_NAT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "mul-nat") == 0) { - emit_opcode(vm, OP_MUL_NAT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "div-nat") == 0) { - emit_opcode(vm, OP_DIV_NAT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "abs-nat") == 0) { - emit_opcode(vm, OP_ABS_INT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "neg-nat") == 0) { - emit_opcode(vm, OP_NEG_INT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "add-real") == 0) { - emit_opcode(vm, OP_ADD_REAL); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "sub-real") == 0) { - emit_opcode(vm, OP_SUB_REAL); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "mul-real") == 0) { - emit_opcode(vm, OP_MUL_REAL); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "div-real") == 0) { - emit_opcode(vm, OP_DIV_REAL); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "abs-real") == 0) { - emit_opcode(vm, OP_ABS_INT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "neg-real") == 0) { - emit_opcode(vm, OP_NEG_INT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - } else if (strcmp(opname, "int-to-real") == 0) { - emit_opcode(vm, OP_INT_TO_REAL); - int dest = parse_register(node->children[0]->token); - int src = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src); - } else if (strcmp(opname, "nat-to-real") == 0) { - emit_opcode(vm, OP_NAT_TO_REAL); - int dest = parse_register(node->children[0]->token); - int src = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src); - } else if (strcmp(opname, "real-to-int") == 0) { - emit_opcode(vm, OP_REAL_TO_INT); - int dest = parse_register(node->children[0]->token); - int src = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src); - } else if (strcmp(opname, "real-to-nat") == 0) { - emit_opcode(vm, OP_REAL_TO_NAT); - int dest = parse_register(node->children[0]->token); - int src = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src); - } else if (strcmp(opname, "jump-eq-int") == 0) { - emit_opcode(vm, OP_JEQ_INT); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-neq-int") == 0) { - emit_opcode(vm, OP_JNEQ_INT); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-gt-int") == 0) { - emit_opcode(vm, OP_JGT_INT); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-lt-int") == 0) { - emit_opcode(vm, OP_JLT_INT); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-le-int") == 0) { - emit_opcode(vm, OP_JLE_INT); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-ge-int") == 0) { - emit_opcode(vm, OP_JGE_INT); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-eq-nat") == 0) { - emit_opcode(vm, OP_JEQ_NAT); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-neq-nat") == 0) { - emit_opcode(vm, OP_JNEQ_NAT); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-gt-nat") == 0) { - emit_opcode(vm, OP_JGT_NAT); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-lt-nat") == 0) { - emit_opcode(vm, OP_JLT_NAT); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-le-nat") == 0) { - emit_opcode(vm, OP_JLE_NAT); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-ge-nat") == 0) { - emit_opcode(vm, OP_JGE_NAT); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-eq-real") == 0) { - emit_opcode(vm, OP_JEQ_REAL); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-neq-real") == 0) { - emit_opcode(vm, OP_JNEQ_REAL); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-gt-real") == 0) { - emit_opcode(vm, OP_JGT_REAL); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-lt-real") == 0) { - emit_opcode(vm, OP_JLT_REAL); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-le-real") == 0) { - emit_opcode(vm, OP_JLE_REAL); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "jump-ge-real") == 0) { - emit_opcode(vm, OP_JGE_REAL); - u32 addr = resolve_symbol(table, node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_u32(vm, addr); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "string-length") == 0) { - emit_opcode(vm, OP_STRLEN); - int dest = parse_register(node->children[0]->token); - int src = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src); - } else if (strcmp(opname, "string-eq") == 0) { - emit_opcode(vm, OP_STREQ); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "string-concat") == 0) { - emit_opcode(vm, OP_STRCAT); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "string-get-char") == 0) { - emit_opcode(vm, OP_STR_GET_CHAR); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "string-find-char") == 0) { - emit_opcode(vm, OP_STR_FIND_CHAR); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - } else if (strcmp(opname, "string-slice") == 0) { - emit_opcode(vm, OP_STR_SLICE); - int dest = parse_register(node->children[0]->token); - int src1 = parse_register(node->children[1]->token); - int src2 = parse_register(node->children[2]->token); - int src3 = parse_register(node->children[3]->token); - emit_byte(vm, dest); - emit_byte(vm, src1); - emit_byte(vm, src2); - emit_byte(vm, src3); - } else if (strcmp(opname, "int-to-string") == 0) { - emit_opcode(vm, OP_INT_TO_STRING); - int dest = parse_register(node->children[0]->token); - int src = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src); - } else if (strcmp(opname, "nat-to-string") == 0) { - emit_opcode(vm, OP_NAT_TO_STRING); - int dest = parse_register(node->children[0]->token); - int src = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src); - } else if (strcmp(opname, "real-to-string") == 0) { - emit_opcode(vm, OP_REAL_TO_STRING); - int dest = parse_register(node->children[0]->token); - int src = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src); - } else if (strcmp(opname, "string-to-int") == 0) { - emit_opcode(vm, OP_STRING_TO_INT); - int dest = parse_register(node->children[0]->token); - int src = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src); - } else if (strcmp(opname, "string-to-nat") == 0) { - emit_opcode(vm, OP_STRING_TO_NAT); - int dest = parse_register(node->children[0]->token); - int src = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src); - } else if (strcmp(opname, "string-to-real") == 0) { - emit_opcode(vm, OP_STRING_TO_REAL); - int dest = parse_register(node->children[0]->token); - int src = parse_register(node->children[1]->token); - emit_byte(vm, dest); - emit_byte(vm, src); - } else { - fprintf(stderr, "Unknown opcode: %s\n", opname); - } -} - -void assemble(VM *vm, ExprNode *program) { - SymbolTable table; - symbol_table_init(&table); - - // PASS 1: Collect all symbols (both code and data) - collect_symbols(&table, program); - - // PASS 2: Process data section using symbol table - for (size_t i = 0; i < program->child_count; ++i) { - ExprNode *section = program->children[i]; - if (strcmp(section->token, "data") == 0) { - process_data_block(vm, &table, section); - } - } - - // PASS 3: Process code section using complete symbol table - for (size_t i = 0; i < program->child_count; ++i) { - ExprNode *section = program->children[i]; - if (strcmp(section->token, "code") == 0) { - for (size_t j = 0; j < section->child_count; ++j) { - process_code_expr(vm, &table, section->children[j]); - } - } - } - - // Cleanup symbol table - for (int i = 0; i < table.count; i++) { -#ifdef ASM_DEBUG - Symbol s = table.symbols[i]; - printf("%s[%d]\n", s.name, s.address); -#endif - free(table.symbols[i].name); - } - free(table.symbols); -} + } while (token.type != TOKEN_EOF); +} \ No newline at end of file diff --git a/src/tools/assembler/assembler.h b/src/tools/assembler/assembler.h index 26864a3..1b3c38a 100644 --- a/src/tools/assembler/assembler.h +++ b/src/tools/assembler/assembler.h @@ -1,20 +1,10 @@ -#ifndef ASSEMBLER_H -#define ASSEMBLER_H +#ifndef UNDAR_IR_ASSEMBLER_H +#define UNDAR_IR_ASSEMBLER_H #include "../../vm/common.h" -#include "../../vm/vm.h" -#include "parser.h" +#include "../../vm/opcodes.h" +#include "lexer.h" -#include -#include -#include -#include +void assemble(VM *vm, char *source); -#define AS_FIXED(v) ((float)(i32)(v) / 65536.0f) -#define TO_FIXED(f) ((i32)( \ - ((f) >= 0.0f) ? ((f) * 65536.0f + 0.5f) : ((f) * 65536.0f - 0.5f) \ -)) - -void assemble(VM *vm, ExprNode *program); - -#endif +#endif \ No newline at end of file diff --git a/src/tools/lexer.c b/src/tools/assembler/lexer.c similarity index 99% rename from src/tools/lexer.c rename to src/tools/assembler/lexer.c index 82c88fc..b634dc5 100644 --- a/src/tools/lexer.c +++ b/src/tools/assembler/lexer.c @@ -1,6 +1,6 @@ #include -#include "../vm/common.h" +#include "../../vm/common.h" #include "lexer.h" typedef struct { diff --git a/src/tools/lexer.h b/src/tools/assembler/lexer.h similarity index 100% rename from src/tools/lexer.h rename to src/tools/assembler/lexer.h diff --git a/src/tools/old_assembler/assembler.c b/src/tools/old_assembler/assembler.c new file mode 100644 index 0000000..e66be6b --- /dev/null +++ b/src/tools/old_assembler/assembler.c @@ -0,0 +1,1211 @@ +#include "assembler.h" +#include "parser.h" +typedef enum { SYMBOL_CODE, SYMBOL_DATA } SymbolType; + +typedef struct { + char *name; + u32 address; + SymbolType type; + int size; // How much memory this symbol occupies + int is_constant; // 1 = constant, 0 = variable +} Symbol; + +typedef struct { + Symbol *symbols; + int count; + int capacity; +} SymbolTable; + +void symbol_table_init(SymbolTable *table) { + table->capacity = 32; + table->count = 0; + table->symbols = malloc(table->capacity * sizeof(Symbol)); +} + +void symbol_table_add(SymbolTable *table, const char *name, u32 address, + SymbolType type) { + // Check for duplicates + for (int i = 0; i < table->count; i++) { + if (strcmp(table->symbols[i].name, name) == 0) { + fprintf(stderr, "Error: Duplicate label '%s'\n", name); + exit(1); + } + } + + if (table->count >= table->capacity) { + table->capacity *= 2; + table->symbols = realloc(table->symbols, table->capacity * sizeof(Symbol)); + } + + Symbol *sym = &table->symbols[table->count++]; + sym->name = strdup(name); + sym->address = address; + sym->type = type; + sym->size = 4; // Default size + sym->is_constant = 0; +} + +Symbol *symbol_table_lookup(SymbolTable *table, const char *name) { + for (int i = 0; i < table->count; i++) { + if (strcmp(table->symbols[i].name, name) == 0) { + return &table->symbols[i]; + } + } + return NULL; +} + +u32 find_label_in_table(SymbolTable *table, const char *name) { + Symbol *sym = symbol_table_lookup(table, name); + if (!sym) { + fprintf(stderr, "Error: Undefined label '%s'\n", name); + exit(1); + } + return sym->address; +} + +int get_instruction_byte_size(ExprNode *node) { + const char *opname = node->token; + + // Return (1 + 1) + if (strcmp(opname, "return") == 0) { + return 2; // 1 byte opcode + 1 byte return register + } + + if (strcmp(opname, "neg-int") == 0 || + strcmp(opname, "abs-int") == 0 || + strcmp(opname, "neg-nat") == 0 || + strcmp(opname, "abs-nat") == 0 || + strcmp(opname, "neg-real") == 0 || + strcmp(opname, "abs-real") == 0 || + strcmp(opname, "int-to-string") == 0 || + strcmp(opname, "load-indirect-8") == 0 || + strcmp(opname, "nat-to-string") == 0 || + strcmp(opname, "load-indirect-16") == 0 || + strcmp(opname, "real-to-string") == 0 || + strcmp(opname, "load-indirect-32") == 0 || + strcmp(opname, "int-to-real") == 0 || + strcmp(opname, "store-indirect-8") == 0 || + strcmp(opname, "nat-to-real") == 0 || + strcmp(opname, "store-indirect-16") == 0 || + strcmp(opname, "real-to-int") == 0 || + strcmp(opname, "store-indirect-32") == 0 || + strcmp(opname, "real-to-nat") == 0 || strcmp(opname, "nat-to-int") == 0 || + strcmp(opname, "int-to-nat") == 0 || + strcmp(opname, "string-length") == 0 || + strcmp(opname, "store-absolute-32") == 0 || + strcmp(opname, "store-absolute-8") == 0 || + strcmp(opname, "store-absolute-16") == 0 || + strcmp(opname, "memset") == 0 || strcmp(opname, "memset") == 0 || + strcmp(opname, "memset-8") == 0 || strcmp(opname, "memset-16") == 0 || + strcmp(opname, "register-move") == 0 || strcmp(opname, "malloc") == 0) { + return 3; + } + + // Register-register-register opcodes (4 bytes: 1 + 3) + if (strcmp(opname, "add-int") == 0 || strcmp(opname, "sub-int") == 0 || + strcmp(opname, "mul-int") == 0 || strcmp(opname, "div-int") == 0 || + strcmp(opname, "add-nat") == 0 || strcmp(opname, "sub-nat") == 0 || + strcmp(opname, "mul-nat") == 0 || strcmp(opname, "div-nat") == 0 || + strcmp(opname, "add-real") == 0 || strcmp(opname, "sub-real") == 0 || + strcmp(opname, "bit-shift-left") == 0 || + strcmp(opname, "bit-shift-right") == 0 || + strcmp(opname, "bit-shift-r-ext") == 0 || + strcmp(opname, "bit-and") == 0 || strcmp(opname, "bit-or") == 0 || + strcmp(opname, "bit-xor") == 0 || strcmp(opname, "mul-real") == 0 || + strcmp(opname, "div-real") == 0) { + return 4; + } + + // (5 bytes: 1 + 4) + if (strcmp(opname, "exit") == 0 || strcmp(opname, "jump-if-flag") == 0 || + strcmp(opname, "jump") == 0) { + return 5; + } + + // Load, Load-immediate (6 bytes: 1 + 1 + 4) + if (strcmp(opname, "load-absolute-32") == 0 || + strcmp(opname, "load-immediate") == 0 || + strcmp(opname, "load-absolute-16") == 0 || + strcmp(opname, "load-absolute-8") == 0) { + return 6; + } + + // jump compare (7 bytes: 1 + 4 + 1 + 1) + if (strcmp(opname, "jump-eq-int") == 0 || + strcmp(opname, "jump-neq-int") == 0 || + strcmp(opname, "jump-gt-int") == 0 || + strcmp(opname, "jump-lt-int") == 0 || + strcmp(opname, "jump-le-int") == 0 || + strcmp(opname, "jump-ge-int") == 0 || + strcmp(opname, "jump-eq-nat") == 0 || + strcmp(opname, "jump-neq-nat") == 0 || + strcmp(opname, "jump-gt-nat") == 0 || + strcmp(opname, "jump-lt-nat") == 0 || + strcmp(opname, "jump-le-nat") == 0 || + strcmp(opname, "jump-ge-nat") == 0 || + strcmp(opname, "jump-eq-real") == 0 || + strcmp(opname, "jump-neq-real") == 0 || + strcmp(opname, "jump-gt-real") == 0 || + strcmp(opname, "jump-lt-real") == 0 || + strcmp(opname, "jump-le-real") == 0 || + strcmp(opname, "jump-ge-real") == 0 || + strcmp(opname, "store-offset-8") == 0 || + strcmp(opname, "store-offset-16") == 0 || + strcmp(opname, "store-offset-32") == 0 || + strcmp(opname, "load-offset-8") == 0 || + strcmp(opname, "load-offset-16") == 0 || + strcmp(opname, "load-offset-32") == 0) { + return 7; + } + + // Call (1 + 4 + 1 + args + 1) + if (strcmp(opname, "call") == 0) { + ExprNode *args_node = node->children[1]; + u32 args_count; + + if (strcmp(args_node->token, "nil") == 0) { + args_count = 0; + } else { + args_count = 1 + args_node->child_count; + } + + return 1 + 1 + 1 + 4 + args_count; + } + + // Syscall (1 + syscall_id (4) + args) + if (strcmp(opname, "syscall") == 0) { + return 1 + 4 + (node->child_count > 0 ? node->child_count - 1 : 0); + } + + fprintf(stderr, "Unknown opcode for sizing: %s\n", opname); + exit(-1); +} + +int calculate_instruction_size(ExprNode *node) { + if (node->child_count == 0) + return 0; + + return get_instruction_byte_size(node); +} + +void collect_symbols_in_node(SymbolTable *table, ExprNode *node, + u32 *current_addr, int depth) { + char indent[32] = ""; + for (int i = 0; i < depth; i++) + strcat(indent, " "); + +#ifdef ASM_DEBUG + printf("%s%d %s ", indent, *current_addr, node->token); +#endif + + if (strcmp(node->token, "label") == 0) { + if (node->child_count >= 1) { + const char *name = node->children[0]->token; +#ifdef ASM_DEBUG + printf(" %s -> %d\n", name, *current_addr); +#endif + symbol_table_add(table, name, *current_addr, SYMBOL_CODE); + } + + for (size_t i = 1; i < node->child_count; i++) { + collect_symbols_in_node(table, node->children[i], current_addr, + depth + 1); + } + } else { + int size = get_instruction_byte_size(node); + *current_addr += size; +#ifdef ASM_DEBUG + printf(" +%d bytes -> %d\n", size, *current_addr); +#endif + } +} + +void collect_symbols(SymbolTable *table, ExprNode *program) { + // First, collect all data labels (with placeholder address) + for (size_t i = 0; i < program->child_count; ++i) { + ExprNode *section = program->children[i]; + if (strcmp(section->token, "data") == 0) { + for (size_t j = 0; j < section->child_count; ++j) { + ExprNode *item = section->children[j]; + if (strcmp(item->token, "label") == 0 && item->child_count >= 2) { + const char *name = item->children[0]->token; + symbol_table_add(table, name, 0, SYMBOL_DATA); + } + } + } + } + + // Second, collect all code labels with proper nesting + u32 code_addr = 0; + for (size_t i = 0; i < program->child_count; ++i) { + ExprNode *section = program->children[i]; + if (strcmp(section->token, "code") == 0) { + for (size_t j = 0; j < section->child_count; ++j) { + collect_symbols_in_node(table, section->children[j], &code_addr, 0); + } + } + } +} + +u32 allocate_data(VM *vm, SymbolTable *table, const char *name, u32 size) { + u32 addr = vm->mp; + vm->mp += size; + vm->frames[vm->fp].end += size; + + // Update the symbol's address + Symbol *sym = symbol_table_lookup(table, name); + if (sym && sym->type == SYMBOL_DATA) { + sym->address = addr; + sym->size = size; + } + + return addr; +} + +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); } + +int parse_register(const char *reg_str) { + if (reg_str[0] != '$') + return -1; + return atoi(reg_str + 1); +} + +u32 resolve_symbol(SymbolTable *table, const char *ref) { + // Handle symbol references (e.g., &label) + if (ref[0] == '&') { + return find_label_in_table(table, ref + 1); + } + + // Handle fixed-point numbers (e.g., 0.5) + if (strchr(ref, '.')) { + return TO_FIXED(atof(ref)); + } + + // Handle hexadecimal literals (e.g., 0x7) + if (ref[0] == '0' && (ref[1] == 'x' || ref[1] == 'X')) { + char *endptr; + u32 value = (u32)strtoul(ref + 2, &endptr, 16); // Skip "0x" + + if (endptr == ref + 2 || *endptr != '\0') { + fprintf(stderr, "Invalid hex literal: %s\n", ref); + exit(1); + } + return value; + } + + // Handle decimal literals (e.g., 7) + char *endptr; + u32 value = (u32)strtoul(ref, &endptr, 10); + + if (endptr == ref || *endptr != '\0') { + fprintf(stderr, "Invalid decimal literal: %s\n", ref); + exit(1); + } + return value; +} + +static char *unwrap_string(const char *quoted_str) { + if (!quoted_str) + return NULL; + + size_t len = strlen(quoted_str); + if (len >= 2 && quoted_str[0] == '"' && quoted_str[len - 1] == '"') { + // Remove quotes and process escape sequences + const char *src = quoted_str + 1; + size_t src_len = len - 2; + + // First pass: calculate the actual length needed after escape processing + size_t actual_len = 0; + for (size_t i = 0; i < src_len; ++i) { + if (src[i] == '\\' && i + 1 < src_len) { + // Escape sequence + actual_len++; + i++; // Skip the next character + } else { + actual_len++; + } + } + + char *unwrapped = (char *)malloc(actual_len + 1); + size_t dst_idx = 0; + + // Second pass: process escape sequences + for (size_t i = 0; i < src_len; ++i) { + if (src[i] == '\\' && i + 1 < src_len) { + // Handle escape sequences + switch (src[i + 1]) { + case 'n': + unwrapped[dst_idx++] = '\n'; + break; + case 't': + unwrapped[dst_idx++] = '\t'; + break; + case 'r': + unwrapped[dst_idx++] = '\r'; + break; + case '\\': + unwrapped[dst_idx++] = '\\'; + break; + case '"': + unwrapped[dst_idx++] = '"'; + break; + case '\'': + unwrapped[dst_idx++] = '\''; + break; + default: + // Unknown escape, keep both characters + unwrapped[dst_idx++] = src[i]; + unwrapped[dst_idx++] = src[i + 1]; + break; + } + i++; // Skip the next character + } else { + unwrapped[dst_idx++] = src[i]; + } + } + unwrapped[dst_idx] = '\0'; + return unwrapped; + } + // Not quoted, return copy + return strdup(quoted_str); +} + +void process_data_block(VM *vm, SymbolTable *table, ExprNode *block) { + for (size_t i = 0; i < block->child_count; ++i) { + ExprNode *item = block->children[i]; + if (strcmp(item->token, "label") == 0 && item->child_count >= 2) { + const char *name = item->children[0]->token; + ExprNode *val = item->children[1]; + + if (val->child_count == 0) { + const char *token = val->token; + + // Case 1: String literal (enclosed in quotes) + if (token[0] == '"' && token[strlen(token) - 1] == '"') { + char *unwrapped = unwrap_string(token); + int len = strlen(unwrapped); + u32 addr = allocate_data(vm, table, name, len + 1 + 4); + + write_u32(vm, memory, addr, len); + for (int i = 0; i < len; i++) { + write_u8(vm, memory, addr + 4 + i, unwrapped[i]); + } + write_u8(vm, memory, addr + 4 + len, '\0'); + free(unwrapped); + } + // Case 2: Hexadecimal integer (0x...) + else if (token[0] == '0' && (token[1] == 'x' || token[1] == 'X')) { + char *endptr; + u32 value = (u32)strtoul(token + 2, &endptr, 16); + + if (endptr != token + strlen(token)) { + fprintf(stderr, "Invalid hex in data block: %s\n", token); + exit(1); + } + + u32 addr = allocate_data(vm, table, name, 4); + write_u32(vm, memory, addr, value); + } + // Case 3: Floating-point (has decimal point) + else if (strchr(token, '.')) { + float f = atof(token); + u32 addr = allocate_data(vm, table, name, 4); + write_u32(vm, memory, addr, TO_FIXED(f)); + } + // Case 4: Decimal integer + else { + char *endptr; + u32 value = (u32)strtoul(token, &endptr, 10); + + if (endptr != token + strlen(token)) { + fprintf(stderr, "Invalid decimal in data block: %s\n", token); + exit(1); + } + + u32 addr = allocate_data(vm, table, name, 4); + write_u32(vm, memory, addr, value); + //vm->mp += 4; + } + } else { + fprintf(stderr, "Unsupported data item\n"); + exit(1); + } + } + } +} + +void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) { + const char *opname = node->token; + if (strcmp(opname, "label") == 0) { + for (size_t i = 1; i < node->child_count; i++) { + process_code_expr(vm, table, node->children[i]); + } + } else if (strcmp(opname, "exit") == 0) { + emit_opcode(vm, OP_EXIT); + u32 addr = resolve_symbol(table, node->children[0]->token); + emit_u32(vm, addr); + } else if (strcmp(opname, "jump") == 0) { + emit_opcode(vm, OP_JMP); + u32 addr = resolve_symbol(table, node->children[0]->token); + emit_u32(vm, addr); + } else if (strcmp(opname, "jump-if-flag") == 0) { + emit_opcode(vm, OP_JMPF); + u32 addr = resolve_symbol(table, node->children[0]->token); + emit_u32(vm, addr); + } else if (strcmp(opname, "call") == 0) { + emit_opcode(vm, OP_CALL); + + if (node->child_count < 3) { + fprintf(stderr, "Error: call requires (args) and return register\n"); + return; + } + + // Parse function address (first child) + u32 addr = resolve_symbol(table, node->children[0]->token); + if (addr == (u32)-1) { + fprintf(stderr, "Error: undefined symbol '%s'\n", + node->children[0]->token); + return; + } + emit_u32(vm, addr); + + // Parse argument list (second child) + ExprNode *args_node = node->children[1]; + u8 arg_count = 0; + + if (args_node->child_count > 0) { + // Multiple arguments case + arg_count = args_node->child_count + 1; // +1 for the token + } else { + // Single argument case - token is the argument + arg_count = (args_node->token[0] != '\0') ? 1 : 0; + } + emit_byte(vm, arg_count); + + // Emit arguments based on representation + if (arg_count > 0) { + // First argument is always the token + const char *reg_str = args_node->token; + int reg = parse_register(reg_str); + if (reg < 0) { + fprintf(stderr, "Error: invalid argument register '%s'\n", reg_str); + return; + } + emit_byte(vm, (u8)reg); + + // Emit children if present + for (size_t i = 0; i < args_node->child_count; i++) { + reg_str = args_node->children[i]->token; + reg = parse_register(reg_str); + if (reg < 0) { + fprintf(stderr, "Error: invalid argument register '%s'\n", reg_str); + return; + } + emit_byte(vm, (u8)reg); + } + } + // Parse return register (third child) + const char *return_reg_str = node->children[2]->token; + int return_reg = parse_register(return_reg_str); + + if (return_reg < 0) { + if (strcmp(return_reg_str, "nil") == 0) { + return_reg = 0xFF; + } else { + fprintf(stderr, "Error: invalid return register '%s'\n", + return_reg_str); + return; + } + } + emit_byte(vm, (u8)return_reg); + +} else if (strcmp(opname, "return") == 0) { + emit_opcode(vm, OP_RETURN); + + if (node->child_count != 1) { + fprintf(stderr, "Error: return requires exactly one argument\n"); + return; + } + + const char *reg_str = node->children[0]->token; + int reg = parse_register(reg_str); + + // Handle "nil" as special case (no return value) + if (reg < 0) { + if (strcmp(reg_str, "nil") == 0) { + reg = 0xFF; // Special value for "no return" + } else { + fprintf(stderr, "Error: invalid return register '%s'\n", reg_str); + return; + } + } + emit_byte(vm, (u8)reg); + } else if (strcmp(opname, "load-immediate") == 0) { + emit_opcode(vm, OP_LOAD_IMM); + int reg = parse_register(node->children[0]->token); + u32 addr = resolve_symbol(table, node->children[1]->token); + emit_byte(vm, reg); + emit_u32(vm, addr); + } else if (strcmp(opname, "load-absolute-8") == 0) { + emit_opcode(vm, OP_LOAD_ABS_8); + int dest = parse_register(node->children[0]->token); + u32 addr = resolve_symbol(table, node->children[1]->token); + emit_byte(vm, dest); + emit_u32(vm, addr); + } else if (strcmp(opname, "load-absolute-16") == 0) { + emit_opcode(vm, OP_LOAD_ABS_16); + int dest = parse_register(node->children[0]->token); + u32 addr = resolve_symbol(table, node->children[1]->token); + emit_byte(vm, dest); + emit_u32(vm, addr); + } else if (strcmp(opname, "load-absolute-32") == 0) { + emit_opcode(vm, OP_LOAD_ABS_32); + int dest = parse_register(node->children[0]->token); + u32 addr = resolve_symbol(table, node->children[1]->token); + emit_byte(vm, dest); + emit_u32(vm, addr); + } else if (strcmp(opname, "load-indirect-8") == 0) { + emit_opcode(vm, OP_LOAD_IND_8); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "load-indirect-16") == 0) { + emit_opcode(vm, OP_LOAD_IND_16); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "load-indirect-32") == 0) { + emit_opcode(vm, OP_LOAD_IND_32); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "malloc") == 0) { + emit_opcode(vm, OP_MALLOC); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "memset-8") == 0) { + emit_opcode(vm, OP_MEMSET_8); + int dest = parse_register(node->children[0]->token); + int value = parse_register(node->children[1]->token); + int count = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, value); + emit_byte(vm, count); + } else if (strcmp(opname, "memset-16") == 0) { + emit_opcode(vm, OP_MEMSET_16); + int dest = parse_register(node->children[0]->token); + int value = parse_register(node->children[1]->token); + int count = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, value); + emit_byte(vm, count); + } else if (strcmp(opname, "memset") == 0) { + emit_opcode(vm, OP_MEMSET_32); + int dest = parse_register(node->children[0]->token); + int value = parse_register(node->children[1]->token); + int count = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, value); + emit_byte(vm, count); + } else if (strcmp(opname, "store-absolute-8") == 0) { + emit_opcode(vm, OP_STORE_ABS_8); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "store-absolute-16") == 0) { + emit_opcode(vm, OP_STORE_ABS_16); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "store-absolute-32") == 0) { + emit_opcode(vm, OP_STORE_ABS_32); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "store-indirect-8") == 0) { + emit_opcode(vm, OP_STORE_IND_8); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "store-indirect-16") == 0) { + emit_opcode(vm, OP_STORE_IND_16); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "store-indirect-32") == 0) { + emit_opcode(vm, OP_STORE_IND_32); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "store-offset-8") == 0) { + emit_opcode(vm, OP_STORE_OFF_8); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + u32 addr = resolve_symbol(table, node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_u32(vm, addr); + } else if (strcmp(opname, "store-offset-16") == 0) { + emit_opcode(vm, OP_STORE_OFF_16); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + u32 addr = resolve_symbol(table, node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_u32(vm, addr); + } else if (strcmp(opname, "store-offset-32") == 0) { + emit_opcode(vm, OP_STORE_OFF_32); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + u32 addr = resolve_symbol(table, node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_u32(vm, addr); + } else if (strcmp(opname, "load-offset-8") == 0) { + emit_opcode(vm, OP_LOAD_OFF_8); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + u32 addr = resolve_symbol(table, node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_u32(vm, addr); + } else if (strcmp(opname, "load-offset-16") == 0) { + emit_opcode(vm, OP_LOAD_OFF_16); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + u32 addr = resolve_symbol(table, node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_u32(vm, addr); + } else if (strcmp(opname, "load-offset-32") == 0) { + emit_opcode(vm, OP_LOAD_OFF_32); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + u32 addr = resolve_symbol(table, node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_u32(vm, addr); + } else if (strcmp(opname, "register-move") == 0) { + emit_opcode(vm, OP_REG_MOV); + int dest = parse_register(node->children[0]->token); + int src = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src); + } else if (strcmp(opname, "syscall") == 0) { + emit_opcode(vm, OP_SYSCALL); + + // Parse syscall ID + u32 syscall_id = 0; + const char *syscall_name = node->children[0]->token; + if (strcmp(syscall_name, "EXIT") == 0) + syscall_id = SYSCALL_EXIT; + else if (strcmp(syscall_name, "OPEN") == 0) + syscall_id = SYSCALL_DEVICE_OPEN; + else if (strcmp(syscall_name, "READ") == 0) + syscall_id = SYSCALL_DEVICE_READ; + else if (strcmp(syscall_name, "WRITE") == 0) + syscall_id = SYSCALL_DEVICE_WRITE; + else if (strcmp(syscall_name, "CLOSE") == 0) + syscall_id = SYSCALL_DEVICE_CLOSE; + else if (strcmp(syscall_name, "IOCTL") == 0) + syscall_id = SYSCALL_DEVICE_IOCTL; + else if (strcmp(syscall_name, "REFRESH") == 0) + syscall_id = SYSCALL_DEVICE_REFRESH; + + emit_u32(vm, syscall_id); + + // Emit register arguments + for (size_t i = 1; i < node->child_count; ++i) { + int reg = parse_register(node->children[i]->token); + emit_byte(vm, reg); + } + } else if (strcmp(opname, "bit-shift-left") == 0) { + emit_opcode(vm, OP_BIT_SHIFT_LEFT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "bit-shift-right") == 0) { + emit_opcode(vm, OP_BIT_SHIFT_RIGHT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "bit-shift-r-ext") == 0) { + emit_opcode(vm, OP_BIT_SHIFT_R_EXT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "bit-and") == 0) { + emit_opcode(vm, OP_BAND); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "bit-or") == 0) { + emit_opcode(vm, OP_BOR); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "bit-xor") == 0) { + emit_opcode(vm, OP_BXOR); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "add-int") == 0) { + emit_opcode(vm, OP_ADD_INT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "sub-int") == 0) { + emit_opcode(vm, OP_SUB_INT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "mul-int") == 0) { + emit_opcode(vm, OP_MUL_INT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "div-int") == 0) { + emit_opcode(vm, OP_DIV_INT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "abs-int") == 0) { + emit_opcode(vm, OP_ABS_INT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "neg-int") == 0) { + emit_opcode(vm, OP_NEG_INT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "add-nat") == 0) { + emit_opcode(vm, OP_ADD_NAT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "sub-nat") == 0) { + emit_opcode(vm, OP_SUB_NAT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "mul-nat") == 0) { + emit_opcode(vm, OP_MUL_NAT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "div-nat") == 0) { + emit_opcode(vm, OP_DIV_NAT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "abs-nat") == 0) { + emit_opcode(vm, OP_ABS_INT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "neg-nat") == 0) { + emit_opcode(vm, OP_NEG_INT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "add-real") == 0) { + emit_opcode(vm, OP_ADD_REAL); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "sub-real") == 0) { + emit_opcode(vm, OP_SUB_REAL); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "mul-real") == 0) { + emit_opcode(vm, OP_MUL_REAL); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "div-real") == 0) { + emit_opcode(vm, OP_DIV_REAL); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "abs-real") == 0) { + emit_opcode(vm, OP_ABS_INT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "neg-real") == 0) { + emit_opcode(vm, OP_NEG_INT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "int-to-real") == 0) { + emit_opcode(vm, OP_INT_TO_REAL); + int dest = parse_register(node->children[0]->token); + int src = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src); + } else if (strcmp(opname, "nat-to-real") == 0) { + emit_opcode(vm, OP_NAT_TO_REAL); + int dest = parse_register(node->children[0]->token); + int src = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src); + } else if (strcmp(opname, "real-to-int") == 0) { + emit_opcode(vm, OP_REAL_TO_INT); + int dest = parse_register(node->children[0]->token); + int src = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src); + } else if (strcmp(opname, "real-to-nat") == 0) { + emit_opcode(vm, OP_REAL_TO_NAT); + int dest = parse_register(node->children[0]->token); + int src = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src); + } else if (strcmp(opname, "jump-eq-int") == 0) { + emit_opcode(vm, OP_JEQ_INT); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-neq-int") == 0) { + emit_opcode(vm, OP_JNEQ_INT); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-gt-int") == 0) { + emit_opcode(vm, OP_JGT_INT); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-lt-int") == 0) { + emit_opcode(vm, OP_JLT_INT); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-le-int") == 0) { + emit_opcode(vm, OP_JLE_INT); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-ge-int") == 0) { + emit_opcode(vm, OP_JGE_INT); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-eq-nat") == 0) { + emit_opcode(vm, OP_JEQ_NAT); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-neq-nat") == 0) { + emit_opcode(vm, OP_JNEQ_NAT); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-gt-nat") == 0) { + emit_opcode(vm, OP_JGT_NAT); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-lt-nat") == 0) { + emit_opcode(vm, OP_JLT_NAT); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-le-nat") == 0) { + emit_opcode(vm, OP_JLE_NAT); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-ge-nat") == 0) { + emit_opcode(vm, OP_JGE_NAT); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-eq-real") == 0) { + emit_opcode(vm, OP_JEQ_REAL); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-neq-real") == 0) { + emit_opcode(vm, OP_JNEQ_REAL); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-gt-real") == 0) { + emit_opcode(vm, OP_JGT_REAL); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-lt-real") == 0) { + emit_opcode(vm, OP_JLT_REAL); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-le-real") == 0) { + emit_opcode(vm, OP_JLE_REAL); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "jump-ge-real") == 0) { + emit_opcode(vm, OP_JGE_REAL); + u32 addr = resolve_symbol(table, node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_u32(vm, addr); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "string-length") == 0) { + emit_opcode(vm, OP_STRLEN); + int dest = parse_register(node->children[0]->token); + int src = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src); + } else if (strcmp(opname, "string-eq") == 0) { + emit_opcode(vm, OP_STREQ); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "string-concat") == 0) { + emit_opcode(vm, OP_STRCAT); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "string-get-char") == 0) { + emit_opcode(vm, OP_STR_GET_CHAR); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "string-find-char") == 0) { + emit_opcode(vm, OP_STR_FIND_CHAR); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + } else if (strcmp(opname, "string-slice") == 0) { + emit_opcode(vm, OP_STR_SLICE); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + int src2 = parse_register(node->children[2]->token); + int src3 = parse_register(node->children[3]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + emit_byte(vm, src2); + emit_byte(vm, src3); + } else if (strcmp(opname, "int-to-string") == 0) { + emit_opcode(vm, OP_INT_TO_STRING); + int dest = parse_register(node->children[0]->token); + int src = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src); + } else if (strcmp(opname, "nat-to-string") == 0) { + emit_opcode(vm, OP_NAT_TO_STRING); + int dest = parse_register(node->children[0]->token); + int src = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src); + } else if (strcmp(opname, "real-to-string") == 0) { + emit_opcode(vm, OP_REAL_TO_STRING); + int dest = parse_register(node->children[0]->token); + int src = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src); + } else if (strcmp(opname, "string-to-int") == 0) { + emit_opcode(vm, OP_STRING_TO_INT); + int dest = parse_register(node->children[0]->token); + int src = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src); + } else if (strcmp(opname, "string-to-nat") == 0) { + emit_opcode(vm, OP_STRING_TO_NAT); + int dest = parse_register(node->children[0]->token); + int src = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src); + } else if (strcmp(opname, "string-to-real") == 0) { + emit_opcode(vm, OP_STRING_TO_REAL); + int dest = parse_register(node->children[0]->token); + int src = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src); + } else { + fprintf(stderr, "Unknown opcode: %s\n", opname); + } +} + +void old_assemble(VM *vm, ExprNode *program) { + SymbolTable table; + symbol_table_init(&table); + + // PASS 1: Collect all symbols (both code and data) + collect_symbols(&table, program); + + // PASS 2: Process data section using symbol table + for (size_t i = 0; i < program->child_count; ++i) { + ExprNode *section = program->children[i]; + if (strcmp(section->token, "data") == 0) { + process_data_block(vm, &table, section); + } + } + + // PASS 3: Process code section using complete symbol table + for (size_t i = 0; i < program->child_count; ++i) { + ExprNode *section = program->children[i]; + if (strcmp(section->token, "code") == 0) { + for (size_t j = 0; j < section->child_count; ++j) { + process_code_expr(vm, &table, section->children[j]); + } + } + } + + // Cleanup symbol table + for (int i = 0; i < table.count; i++) { +#ifdef ASM_DEBUG + Symbol s = table.symbols[i]; + printf("%s[%d]\n", s.name, s.address); +#endif + free(table.symbols[i].name); + } + free(table.symbols); +} diff --git a/src/tools/old_assembler/assembler.h b/src/tools/old_assembler/assembler.h new file mode 100644 index 0000000..76b9326 --- /dev/null +++ b/src/tools/old_assembler/assembler.h @@ -0,0 +1,20 @@ +#ifndef ASSEMBLER_H +#define ASSEMBLER_H + +#include "../../vm/common.h" +#include "../../vm/vm.h" +#include "parser.h" + +#include +#include +#include +#include + +#define AS_FIXED(v) ((float)(i32)(v) / 65536.0f) +#define TO_FIXED(f) ((i32)( \ + ((f) >= 0.0f) ? ((f) * 65536.0f + 0.5f) : ((f) * 65536.0f - 0.5f) \ +)) + +void old_assemble(VM *vm, ExprNode *program); + +#endif diff --git a/src/tools/assembler/parser.c b/src/tools/old_assembler/parser.c similarity index 100% rename from src/tools/assembler/parser.c rename to src/tools/old_assembler/parser.c diff --git a/src/tools/assembler/parser.h b/src/tools/old_assembler/parser.h similarity index 100% rename from src/tools/assembler/parser.h rename to src/tools/old_assembler/parser.h diff --git a/src/vm/opcodes.h b/src/vm/opcodes.h index 979c612..f74a18f 100644 --- a/src/vm/opcodes.h +++ b/src/vm/opcodes.h @@ -4,99 +4,100 @@ #include "common.h" typedef enum { - OP_HALT, /* halt : terminate execution with code [src1] */ + OP_EXIT, /* exit : terminate execution with code [src1] */ OP_CALL, /* call : creates a new frame */ OP_RETURN, /* return : returns from a frame to the parent frame */ OP_SYSCALL, /* syscall : src1 src2 src3 src4 more? does a system call based on args */ - OP_LOAD_IMM, /* load-immediate : registers[dest] = constant */ - OP_LOAD_IND_8, /* load-indirect-8 : registers[dest] = memory[registers[src1]] as u8 */ - OP_LOAD_IND_16, /* load-indirect-16 : registers[dest] = memory[registers[src1]] as u8 */ - OP_LOAD_IND_32, /* load-indirect-32 : registers[dest] = memory[registers[src1]] as u32 */ - OP_LOAD_ABS_8, /* load-absolute-8 : registers[dest] = memory[src1 as u32] */ - OP_LOAD_ABS_16, /* load-absolute-16 : registers[dest] = memory[src1 as u32] */ - OP_LOAD_ABS_32, /* load-absolute-32 : registers[dest] = memory[src1 as u32] */ - OP_LOAD_OFF_8, /* load-offset-8 : registers[dest] = memory[registers[src1] + offset] as u8 */ - OP_LOAD_OFF_16, /* load-offset-16 : registers[dest] = memory[registers[src1] + offset] as u16 */ - OP_LOAD_OFF_32, /* load-offset-32 : registers[dest] = memory[registers[src1] + offset] as u32 */ - OP_STORE_ABS_8, /* store-absolute-8 : memory[dest] = src1 && 0xFF */ - OP_STORE_ABS_16, /* store-absolute-16 : memory[dest] = src1 && 0xFFFF */ - OP_STORE_ABS_32, /* store-absolute-32 : memory[dest] = src1 */ - OP_STORE_IND_8, /* store-indirect-8 : memory[dest] = registers[src1] && 0xFF */ - OP_STORE_IND_16, /* store-indirect-16 : memory[dest] = registers[src1] && 0xFFFF*/ - OP_STORE_IND_32, /* store-indirect-32 : memory[dest] = registers[src1] */ - OP_STORE_OFF_8, /* store-offset-8 : memory[registers[dest] + offset] = registers[src1] && 0xFF */ - OP_STORE_OFF_16, /* store-offset-16 : memory[registers[dest] + offset] = registers[src1] && 0xFFFF */ - OP_STORE_OFF_32, /* store-offset-32 : memory[registers[dest] + offset] = registers[src1] */ + OP_LOAD_IMM, /* load_immediate : locals[dest] = constant */ + OP_LOAD_IND_8, /* load_indirect_8 : locals[dest] = memory[locals[src1]] as u8 */ + OP_LOAD_IND_16, /* load_indirect_16 : locals[dest] = memory[locals[src1]] as u8 */ + OP_LOAD_IND_32, /* load_indirect_32 : locals[dest] = memory[locals[src1]] as u32 */ + OP_LOAD_ABS_8, /* load_absolute_8 : locals[dest] = memory[src1 as u32] */ + OP_LOAD_ABS_16, /* load_absolute_16 : locals[dest] = memory[src1 as u32] */ + OP_LOAD_ABS_32, /* load_absolute_32 : locals[dest] = memory[src1 as u32] */ + OP_LOAD_OFF_8, /* load_offset_8 : locals[dest] = memory[locals[src1] + offset] as u8 */ + OP_LOAD_OFF_16, /* load_offset_16 : locals[dest] = memory[locals[src1] + offset] as u16 */ + OP_LOAD_OFF_32, /* load_offset_32 : locals[dest] = memory[locals[src1] + offset] as u32 */ + OP_STORE_ABS_8, /* store_absolute_8 : memory[dest] = src1 && 0xFF */ + OP_STORE_ABS_16, /* store_absolute_16 : memory[dest] = src1 && 0xFFFF */ + OP_STORE_ABS_32, /* store_absolute_32 : memory[dest] = src1 */ + OP_STORE_IND_8, /* store_indirect_8 : memory[dest] = locals[src1] && 0xFF */ + OP_STORE_IND_16, /* store_indirect_16 : memory[dest] = locals[src1] && 0xFFFF*/ + OP_STORE_IND_32, /* store_indirect_32 : memory[dest] = locals[src1] */ + OP_STORE_OFF_8, /* store_offset_8 : memory[locals[dest] + offset] = locals[src1] && 0xFF */ + OP_STORE_OFF_16, /* store_offset_16 : memory[locals[dest] + offset] = locals[src1] && 0xFFFF */ + OP_STORE_OFF_32, /* store_offset_32 : memory[locals[dest] + offset] = locals[src1] */ OP_MALLOC, /* malloc : dest = fat ptr to memory of ((src1 as size) + 4) */ - OP_MEMSET_8, /* memset-8 : dest <-> dest+count = src1 as u8 */ - OP_MEMSET_16, /* memset-16 : dest <-> dest+count = src1 as u8 */ - OP_MEMSET_32, /* memset-32 : dest <-> dest+count = src1 as u32 */ - OP_REG_MOV, /* register-move : registers[dest] = registers[src1] */ - OP_ADD_INT, /* add-int : registers[dest] = registers[src1] + registers[src2] */ - OP_SUB_INT, /* sub-int : registers[dest] = registers[src1] - registers[src2] */ - OP_MUL_INT, /* mul-int : registers[dest] = registers[src1] * registers[src2] */ - OP_DIV_INT, /* div-int : registers[dest] = registers[src1] / registers[src2] */ - OP_ABS_INT, /* abs-int : registers[dest] = | registers[src1] | */ - OP_NEG_INT, /* neg-int : registers[dest] = -registers[src1] */ - OP_ADD_NAT, /* add-nat : registers[dest] = registers[src1] + registers[src2] */ - OP_SUB_NAT, /* sub-nat : registers[dest] = registers[src1] - registers[src2] */ - OP_MUL_NAT, /* mul-nat : registers[dest] = registers[src1] * registers[src2] */ - OP_DIV_NAT, /* div-nat : registers[dest] = registers[src1] / registers[src2] */ - OP_ABS_NAT, /* abs-nat : registers[dest] = | registers[src1] | */ - OP_NEG_NAT, /* neg-nat : registers[dest] = -registers[src1] */ - OP_ADD_REAL, /* add-real : registers[dest] = registers[src1] + registers[src2] */ - OP_SUB_REAL, /* sub-real : registers[dest] = registers[src1] - registers[src2] */ - OP_MUL_REAL, /* mul-real : registers[dest] = registers[src1] * registers[src2] */ - OP_DIV_REAL, /* div-real : registers[dest] = registers[src1] / registers[src2] */ - OP_ABS_REAL, /* abs-real : registers[dest] = | registers[src1] | */ - OP_NEG_REAL, /* neg-real : registers[dest] = -registers[src1] */ - OP_INT_TO_REAL, /* int-to-real : registers[dest] = registers[src1] as real */ - OP_NAT_TO_REAL, /* nat-to-real : registers[dest] = registers[src1] as real */ - OP_REAL_TO_INT, /* real-to-int : registers[dest] = registers[src1] as int */ - OP_REAL_TO_NAT, /* real-to-nat : registers[dest] = registers[src1] as nat */ - OP_BIT_SHIFT_LEFT, /* bit-shift-left : registers[dest] = registers[src1] << registers[src2] */ - OP_BIT_SHIFT_RIGHT,/* bit-shift-right : registers[dest] = registers[src1] >> registers[src2] */ - OP_BIT_SHIFT_R_EXT,/* bit-shift-r-ext : registers[dest] as i32 = registers[src1] >> registers[src2] */ - OP_BAND, /* bit-and : registers[dest] = registers[src1] & registers[src2] */ - OP_BOR, /* bit-or : registers[dest] = registers[src1] | registers[src2] */ - OP_BXOR, /* bit-xor : registers[dest] = registers[src1] ^ registers[src2] */ + OP_MALLOC_IMM, /* malloc_immediate : dest = fat ptr to memory of raw */ + OP_MEMSET_8, /* memset_8 : dest <-> dest+count = src1 as u8 */ + OP_MEMSET_16, /* memset_16 : dest <-> dest+count = src1 as u8 */ + OP_MEMSET_32, /* memset_32 : dest <-> dest+count = src1 as u32 */ + OP_REG_MOV, /* register_move : locals[dest] = locals[src1] */ + OP_ADD_INT, /* add_int : locals[dest] = locals[src1] + locals[src2] */ + OP_SUB_INT, /* sub_int : locals[dest] = locals[src1] _ locals[src2] */ + OP_MUL_INT, /* mul_int : locals[dest] = locals[src1] * locals[src2] */ + OP_DIV_INT, /* div_int : locals[dest] = locals[src1] / locals[src2] */ + OP_ABS_INT, /* abs_int : locals[dest] = | locals[src1] | */ + OP_NEG_INT, /* neg_int : locals[dest] = -locals[src1] */ + OP_ADD_NAT, /* add_nat : locals[dest] = locals[src1] + locals[src2] */ + OP_SUB_NAT, /* sub_nat : locals[dest] = locals[src1] _ locals[src2] */ + OP_MUL_NAT, /* mul_nat : locals[dest] = locals[src1] * locals[src2] */ + OP_DIV_NAT, /* div_nat : locals[dest] = locals[src1] / locals[src2] */ + OP_ABS_NAT, /* abs_nat : locals[dest] = | locals[src1] | */ + OP_NEG_NAT, /* neg_nat : locals[dest] = -locals[src1] */ + OP_ADD_REAL, /* add_real : locals[dest] = locals[src1] + locals[src2] */ + OP_SUB_REAL, /* sub_real : locals[dest] = locals[src1] _ locals[src2] */ + OP_MUL_REAL, /* mul_real : locals[dest] = locals[src1] * locals[src2] */ + OP_DIV_REAL, /* div_real : locals[dest] = locals[src1] / locals[src2] */ + OP_ABS_REAL, /* abs_real : locals[dest] = | locals[src1] | */ + OP_NEG_REAL, /* neg_real : locals[dest] = _locals[src1] */ + OP_INT_TO_REAL, /* int_to_real : locals[dest] = locals[src1] as real */ + OP_NAT_TO_REAL, /* nat_to_real : locals[dest] = locals[src1] as real */ + OP_REAL_TO_INT, /* real_to_int : locals[dest] = locals[src1] as int */ + OP_REAL_TO_NAT, /* real_to_nat : locals[dest] = locals[src1] as nat */ + OP_BIT_SHIFT_LEFT, /* bit_shift_left : locals[dest] = locals[src1] << locals[src2] */ + OP_BIT_SHIFT_RIGHT,/* bit_shift_right : locals[dest] = locals[src1] >> locals[src2] */ + OP_BIT_SHIFT_R_EXT,/* bit_shift_r_ext : locals[dest] as i32 = locals[src1] >> locals[src2] */ + OP_BAND, /* bit_and : locals[dest] = locals[src1] & locals[src2] */ + OP_BOR, /* bit_or : locals[dest] = locals[src1] | locals[src2] */ + OP_BXOR, /* bit_xor : locals[dest] = locals[src1] ^ locals[src2] */ OP_JMP, /* jump : jump to &dest unconditionally */ - OP_JMPF, /* jump-if-flag : jump to &dest if flag != 0 */ - OP_JEQ_INT, /* jump-eq-int : jump to &dest if registers[src1] as int == registers[src2] as int */ - OP_JNEQ_INT, /* jump-neq-int : jump to &dest if registers[src1] as int != registers[src2] as int */ - OP_JGT_INT, /* jump-gt-int : jump to &dest if registers[src1] as int > registers[src2] as int */ - OP_JLT_INT, /* jump-lt-int : jump to &dest if registers[src1] as int < registers[src2] as int */ - OP_JLE_INT, /* jump-le-int : jump to &dest if registers[src1] as int <= registers[src2] as int */ - OP_JGE_INT, /* jump-ge-int : jump to &dest if registers[src1] as int >= registers[src2] as int */ - OP_JEQ_NAT, /* jump-eq-nat : jump to &dest if registers[src1] as nat == registers[src2] as nat */ - OP_JNEQ_NAT, /* jump-neq-nat : jump to &dest if registers[src1] as nat != registers[src2] as nat */ - OP_JGT_NAT, /* jump-gt-nat : jump to &dest if registers[src1] as nat > registers[src2] as nat */ - OP_JLT_NAT, /* jump-lt-nat : jump to &dest if registers[src1] as nat < registers[src2] as nat */ - OP_JLE_NAT, /* jump-le-nat : jump to &dest if registers[src1] as nat <= registers[src2] as nat */ - OP_JGE_NAT, /* jump-ge-nat : jump to &dest if registers[src1] as nat >= registers[src2] as nat */ - OP_JEQ_REAL, /* jump-eq-real : jump to &dest if registers[src1] as real == registers[src2] as real */ - OP_JNEQ_REAL, /* jump-neq-real : jump to &dest if registers[src1] as real != registers[src2] as real */ - OP_JGE_REAL, /* jump-ge-real : jump to &dest if registers[src1] as real >= registers[src2] as real */ - OP_JGT_REAL, /* jump-gt-real : jump to &dest if registers[src1] as real > registers[src2] as real */ - OP_JLT_REAL, /* jump-lt-real : jump to &dest if registers[src1] as real < registers[src2] as real */ - OP_JLE_REAL, /* jump-le-real : jump to &dest if registers[src1] as real <= registers[src2] as real */ - OP_STRLEN, /* string-length : registers[dest] = length of str at src1 ptr */ - OP_STREQ, /* string-eq : registers[dest] = src1 ptr string == src2 ptr string */ - OP_STRCAT, /* string-concat : registers[dest] = ptr of src1 ptr string + src2 ptr string */ - OP_STR_GET_CHAR, /* string-get-char : registers[dest] = ptr of src1 ptr str, src2 index of str */ - OP_STR_FIND_CHAR, /* string-find-char : registers[dest] = ptr of src1 ptr string, src2 nat8 char */ - OP_STR_SLICE, /* string-slice : registers[dest] = ptr of src1 ptr str, src2 start index, src3 end index */ - OP_INT_TO_STRING, /* int-to-string : registers[dest] = src1 as str */ - OP_NAT_TO_STRING, /* nat-to-string : registers[dest] = src1 as str */ - OP_REAL_TO_STRING, /* real-to-string : registers[dest] = src1 as str */ - OP_STRING_TO_INT, /* string-to-int : registers[dest] = src1 as int */ - OP_STRING_TO_NAT, /* string-to-nat : registers[dest] = src1 as nat */ - OP_STRING_TO_REAL /* string-to-real : registers[dest] = src1 as real */ + OP_JMPF, /* jump_if_flag : jump to &dest if flag != 0 */ + OP_JEQ_INT, /* jump_eq_int : jump to &dest if locals[src1] as int == locals[src2] as int */ + OP_JNEQ_INT, /* jump_neq_int : jump to &dest if locals[src1] as int != locals[src2] as int */ + OP_JGT_INT, /* jump_gt_int : jump to &dest if locals[src1] as int > locals[src2] as int */ + OP_JLT_INT, /* jump_lt_int : jump to &dest if locals[src1] as int < locals[src2] as int */ + OP_JLE_INT, /* jump_le_int : jump to &dest if locals[src1] as int <= locals[src2] as int */ + OP_JGE_INT, /* jump_ge_int : jump to &dest if locals[src1] as int >= locals[src2] as int */ + OP_JEQ_NAT, /* jump_eq_nat : jump to &dest if locals[src1] as nat == locals[src2] as nat */ + OP_JNEQ_NAT, /* jump_neq_nat : jump to &dest if locals[src1] as nat != locals[src2] as nat */ + OP_JGT_NAT, /* jump_gt_nat : jump to &dest if locals[src1] as nat > locals[src2] as nat */ + OP_JLT_NAT, /* jump_lt_nat : jump to &dest if locals[src1] as nat < locals[src2] as nat */ + OP_JLE_NAT, /* jump_le_nat : jump to &dest if locals[src1] as nat <= locals[src2] as nat */ + OP_JGE_NAT, /* jump_ge_nat : jump to &dest if locals[src1] as nat >= locals[src2] as nat */ + OP_JEQ_REAL, /* jump_eq_real : jump to &dest if locals[src1] as real == locals[src2] as real */ + OP_JNEQ_REAL, /* jump_neq_real : jump to &dest if locals[src1] as real != locals[src2] as real */ + OP_JGE_REAL, /* jump_ge_real : jump to &dest if locals[src1] as real >= locals[src2] as real */ + OP_JGT_REAL, /* jump_gt_real : jump to &dest if locals[src1] as real > locals[src2] as real */ + OP_JLT_REAL, /* jump_lt_real : jump to &dest if locals[src1] as real < locals[src2] as real */ + OP_JLE_REAL, /* jump_le_real : jump to &dest if locals[src1] as real <= locals[src2] as real */ + OP_STRLEN, /* string_length : locals[dest] = length of str at src1 ptr */ + OP_STREQ, /* string_eq : locals[dest] = src1 ptr string == src2 ptr string */ + OP_STRCAT, /* string_concat : locals[dest] = ptr of src1 ptr string + src2 ptr string */ + OP_STR_GET_CHAR, /* string_get_char : locals[dest] = ptr of src1 ptr str, src2 index of str */ + OP_STR_FIND_CHAR, /* string_find_char : locals[dest] = ptr of src1 ptr string, src2 nat8 char */ + OP_STR_SLICE, /* string_slice : locals[dest] = ptr of src1 ptr str, src2 start index, src3 end index */ + OP_INT_TO_STRING, /* int_to_string : locals[dest] = src1 as str */ + OP_NAT_TO_STRING, /* nat_to_string : locals[dest] = src1 as str */ + OP_REAL_TO_STRING, /* real_to_string : locals[dest] = src1 as str */ + OP_STRING_TO_INT, /* string_to_int : locals[dest] = src1 as int */ + OP_STRING_TO_NAT, /* string_to_nat : locals[dest] = src1 as nat */ + OP_STRING_TO_REAL /* string_to_real : locals[dest] = src1 as real */ } Opcode; #define MAX_REGS 32 typedef struct frame_s { - u32 registers[MAX_REGS]; /* R0-R31 */ + u32 locals[MAX_REGS]; /* R0-R31 */ u32 start; /* start of memory block */ u32 end; /* end of memory block */ u32 return_reg; /* register to store return value in parent */ @@ -130,7 +131,7 @@ typedef struct device_s { char type[DEVICE_TYPE_MAX_LENGTH]; /* e.g., "screen", "mouse", "gpio" */ char path[DEVICE_PATH_MAX_LENGTH]; /* "/dev/screen", "/dev/input/mouse/0", etc. */ - void *data; /* device-specific data */ + void *data; /* device_specific data */ DeviceOps *ops; /* operations vtable */ u32 flags; /* permissions, status, etc. */ u32 handle; /* id for fast access in VM */ diff --git a/src/vm/vm.c b/src/vm/vm.c index ba92c73..a9a27b3 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -17,8 +17,8 @@ vm->pc++; \ src2 = read_u8(vm, code, vm->pc); \ vm->pc++; \ - value = (type)frame->registers[src1]; \ - value2 = (type)frame->registers[src2]; \ + value = (type)frame->locals[src1]; \ + value2 = (type)frame->locals[src2]; \ cond = !!(value op value2); \ mask = -(u32)cond; \ vm->pc = (target & mask) | (vm->pc & ~mask); \ @@ -27,7 +27,7 @@ #define MATH_OP(type, op) \ do { \ - u32 *regs = frame->registers; \ + u32 *regs = frame->locals; \ dest = read_u8(vm, code, vm->pc); \ vm->pc++; \ src1 = read_u8(vm, code, vm->pc); \ @@ -40,7 +40,7 @@ #define BIT_OP(op) \ do { \ - u32 *regs = frame->registers; \ + u32 *regs = frame->locals; \ dest = read_u8(vm, code, vm->pc); \ vm->pc++; \ src1 = read_u8(vm, code, vm->pc); \ @@ -93,7 +93,7 @@ bool step_vm(VM *vm) { frame = &vm->frames[vm->fp]; switch (opcode) { - case OP_HALT: { + case OP_EXIT: { vm->flag = read_u32(vm, code, vm->pc); return false; } @@ -130,7 +130,7 @@ bool step_vm(VM *vm) { heap_mask = 0; for (i = 0; i < N; i++) { src_reg = args[i]; - child->registers[i] = frame->registers[src_reg]; + child->locals[i] = frame->locals[src_reg]; /* Bitmask operation instead of conditional branch */ heap_mask |= ((frame->heap_mask >> src_reg) & 1) << i; @@ -154,7 +154,7 @@ bool step_vm(VM *vm) { parent = &vm->frames[vm->fp - 1]; if (child_return_reg != 0xFF && parent->return_reg != 0xFF) { - value = child->registers[child_return_reg]; + value = child->locals[child_return_reg]; if (is_heap_value(vm, child_return_reg)) { ptr = value; @@ -171,7 +171,7 @@ bool step_vm(VM *vm) { memcopy(vm->memory + new_ptr + 4, vm->memory + ptr + 4, size); parent->end += size + 4; - parent->registers[parent->return_reg] = new_ptr; + parent->locals[parent->return_reg] = new_ptr; parent->heap_mask |= (1 << parent->return_reg); return true; } @@ -184,10 +184,10 @@ bool step_vm(VM *vm) { *(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->locals[parent->return_reg] = new_ptr; parent->heap_mask |= (1 << parent->return_reg); } else { - parent->registers[parent->return_reg] = value; + parent->locals[parent->return_reg] = value; parent->heap_mask &= ~(1 << parent->return_reg); } } @@ -203,8 +203,8 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - frame->registers[dest] = vm->mp; - size = frame->registers[src1]; + frame->locals[dest] = vm->mp; + size = frame->locals[src1]; write_u32(vm, memory, vm->mp, size); vm->mp += (size + 4); set_heap_status(vm, dest, true); /* Mark as heap pointer */ @@ -216,9 +216,9 @@ bool step_vm(VM *vm) { u8 value_reg = read_u8(vm, code, vm->pc++); u8 count_reg = read_u8(vm, code, vm->pc++); - u32 dest = frame->registers[dest_reg]; - u32 value = frame->registers[value_reg]; - u32 count = frame->registers[count_reg]; + u32 dest = frame->locals[dest_reg]; + u32 value = frame->locals[value_reg]; + u32 count = frame->locals[count_reg]; if (count == 0) { vm->flag = 1; @@ -237,7 +237,7 @@ bool step_vm(VM *vm) { write_u32(vm, memory, i, value); } - frame->registers[0] = dest; + frame->locals[0] = dest; vm->flag = 1; return true; } @@ -247,9 +247,9 @@ bool step_vm(VM *vm) { u8 value_reg = read_u8(vm, code, vm->pc++); u8 count_reg = read_u8(vm, code, vm->pc++); - u32 dest = frame->registers[dest_reg]; - u16 value = (u16)(frame->registers[value_reg]); - u32 count = frame->registers[count_reg]; + u32 dest = frame->locals[dest_reg]; + u16 value = (u16)(frame->locals[value_reg]); + u32 count = frame->locals[count_reg]; if (count == 0) { vm->flag = 1; @@ -268,7 +268,7 @@ bool step_vm(VM *vm) { write_u16(vm, memory, i, value); } - frame->registers[0] = dest; + frame->locals[0] = dest; vm->flag = 1; return true; } @@ -278,9 +278,9 @@ bool step_vm(VM *vm) { u8 value_reg = read_u8(vm, code, vm->pc++); u8 count_reg = read_u8(vm, code, vm->pc++); - u32 dest = frame->registers[dest_reg]; - u8 value = (u8)(frame->registers[value_reg]); - u32 count = frame->registers[count_reg]; + u32 dest = frame->locals[dest_reg]; + u8 value = (u8)(frame->locals[value_reg]); + u32 count = frame->locals[count_reg]; if (count == 0) { vm->flag = 1; @@ -299,7 +299,7 @@ bool step_vm(VM *vm) { write_u8(vm, memory, i, value); } - frame->registers[0] = dest; + frame->locals[0] = dest; vm->flag = 1; return true; } @@ -308,7 +308,7 @@ bool step_vm(VM *vm) { vm->pc++; v = read_u32(vm, code, vm->pc); vm->pc += 4; - frame->registers[dest] = v; + frame->locals[dest] = v; return true; } case OP_LOAD_ABS_32: { @@ -317,7 +317,7 @@ bool step_vm(VM *vm) { ptr = read_u32(vm, code, vm->pc); vm->pc += 4; v = read_u32(vm, memory, ptr); - frame->registers[dest] = v; + frame->locals[dest] = v; return true; } case OP_LOAD_ABS_16: { @@ -326,7 +326,7 @@ bool step_vm(VM *vm) { ptr = read_u32(vm, code, vm->pc); vm->pc += 4; v = read_u16(vm, memory, ptr); - frame->registers[dest] = v; + frame->locals[dest] = v; return true; } case OP_LOAD_ABS_8: { @@ -335,7 +335,7 @@ bool step_vm(VM *vm) { ptr = read_u32(vm, code, vm->pc); vm->pc += 4; v = read_u8(vm, memory, ptr); - frame->registers[dest] = v; + frame->locals[dest] = v; return true; } case OP_LOAD_IND_32: { @@ -343,9 +343,9 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - v = frame->registers[src1]; + v = frame->locals[src1]; ptr = read_u32(vm, memory, v); - frame->registers[dest] = ptr; + frame->locals[dest] = ptr; return true; } case OP_LOAD_IND_16: { @@ -354,9 +354,9 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - v = frame->registers[src1]; + v = frame->locals[src1]; v16 = read_u16(vm, memory, v); - frame->registers[dest] = v16; + frame->locals[dest] = v16; return true; } case OP_LOAD_IND_8: { @@ -365,9 +365,9 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - v = frame->registers[src1]; + v = frame->locals[src1]; v8 = read_u8(vm, memory, v); - frame->registers[dest] = v8; + frame->locals[dest] = v8; return true; } case OP_LOAD_OFF_8: { @@ -379,9 +379,9 @@ bool step_vm(VM *vm) { vm->pc++; offset = read_u32(vm, code, vm->pc); vm->pc += 4; - v = frame->registers[src1]; + v = frame->locals[src1]; v8 = read_u8(vm, memory, (v + offset)); - frame->registers[dest] = v8; + frame->locals[dest] = v8; return true; } case OP_LOAD_OFF_16: { @@ -393,9 +393,9 @@ bool step_vm(VM *vm) { vm->pc++; offset = read_u32(vm, code, vm->pc); vm->pc += 4; - v = frame->registers[src1]; + v = frame->locals[src1]; v16 = read_u16(vm, memory, (v + offset)); - frame->registers[dest] = v16; + frame->locals[dest] = v16; return true; } case OP_LOAD_OFF_32: { @@ -406,9 +406,9 @@ bool step_vm(VM *vm) { vm->pc++; offset = read_u32(vm, code, vm->pc); vm->pc += 4; - v = frame->registers[src1]; + v = frame->locals[src1]; ptr = read_u32(vm, memory, (v + offset)); - frame->registers[dest] = ptr; + frame->locals[dest] = ptr; return true; } case OP_STORE_ABS_32: { @@ -416,8 +416,8 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - v = frame->registers[src1]; - ptr = frame->registers[dest]; + v = frame->locals[src1]; + ptr = frame->locals[dest]; write_u32(vm, memory, ptr, v); return true; } @@ -426,8 +426,8 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - v = frame->registers[src1]; - ptr = frame->registers[dest]; + v = frame->locals[src1]; + ptr = frame->locals[dest]; write_u16(vm, memory, ptr, v); return true; } @@ -436,8 +436,8 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - v = frame->registers[src1]; - ptr = frame->registers[dest]; + v = frame->locals[src1]; + ptr = frame->locals[dest]; write_u8(vm, memory, ptr, v); return true; } @@ -446,8 +446,8 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - ptr = frame->registers[dest]; - v = frame->registers[src1]; + ptr = frame->locals[dest]; + v = frame->locals[src1]; write_u32(vm, memory, ptr, v); return true; } @@ -457,8 +457,8 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - ptr = frame->registers[dest]; - v16 = frame->registers[src1]; + ptr = frame->locals[dest]; + v16 = frame->locals[src1]; write_u16(vm, memory, ptr, v16); return true; } @@ -468,8 +468,8 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - ptr = frame->registers[dest]; - v8 = frame->registers[src1]; + ptr = frame->locals[dest]; + v8 = frame->locals[src1]; write_u8(vm, memory, ptr, v8); return true; } @@ -482,8 +482,8 @@ bool step_vm(VM *vm) { vm->pc++; offset = read_u32(vm, code, vm->pc); vm->pc += 4; - ptr = frame->registers[dest]; - v8 = frame->registers[src1]; + ptr = frame->locals[dest]; + v8 = frame->locals[src1]; write_u8(vm, memory, (ptr + offset), v8); return true; } @@ -496,8 +496,8 @@ bool step_vm(VM *vm) { vm->pc++; offset = read_u32(vm, code, vm->pc); vm->pc += 4; - ptr = frame->registers[dest]; - v16 = frame->registers[src1]; + ptr = frame->locals[dest]; + v16 = frame->locals[src1]; write_u16(vm, memory, (ptr + offset), v16); return true; } @@ -509,8 +509,8 @@ bool step_vm(VM *vm) { vm->pc++; offset = read_u32(vm, code, vm->pc); vm->pc += 4; - ptr = frame->registers[dest]; - v = frame->registers[src1]; + ptr = frame->locals[dest]; + v = frame->locals[src1]; write_u32(vm, memory, (ptr + offset), v); return true; } @@ -519,7 +519,7 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - frame->registers[dest] = frame->registers[src1]; + frame->locals[dest] = frame->locals[src1]; if (is_heap_value(vm, src1)) { set_heap_status(vm, dest, true); @@ -559,14 +559,14 @@ bool step_vm(VM *vm) { mode_reg = read_u8(vm, code, vm->pc); vm->pc++; - path_ptr = frame->registers[path_reg]; - mode = frame->registers[mode_reg]; + path_ptr = frame->locals[path_reg]; + mode = frame->locals[mode_reg]; dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]); if (dev) { if (dev->ops->open) { /* return device plex to user */ device_ptr = vm->mp; - frame->registers[dest_reg] = device_ptr; + frame->locals[dest_reg] = device_ptr; /* malloc size for device */ write_u32(vm, memory, device_ptr, dev->size); vm->mp += (dev->size + 4); @@ -594,9 +594,9 @@ bool step_vm(VM *vm) { size_reg = read_u8(vm, code, vm->pc); vm->pc++; - device_ptr = frame->registers[device_reg]; /* device pointer */ - buffer_ptr = frame->registers[buffer_reg]; - size = frame->registers[size_reg]; /* size */ + device_ptr = frame->locals[device_reg]; /* device pointer */ + buffer_ptr = frame->locals[buffer_reg]; + size = frame->locals[size_reg]; /* size */ handle = vm->memory[device_ptr + 4]; /* get device handle */ dev = &vm->devices[handle]; @@ -616,7 +616,7 @@ bool step_vm(VM *vm) { device_reg = read_u8(vm, code, vm->pc); vm->pc++; - device_ptr = frame->registers[device_reg]; /* device pointer */ + device_ptr = frame->locals[device_reg]; /* device pointer */ handle = vm->memory[device_ptr + 4]; /* get device handle */ dev = &vm->devices[handle]; if (dev && dev->ops->refresh) { @@ -639,9 +639,9 @@ bool step_vm(VM *vm) { size_reg = read_u8(vm, code, vm->pc); vm->pc++; - device_ptr = frame->registers[device_reg]; /* device pointer */ - buffer_ptr = frame->registers[buffer_reg]; /* R1: buffer pointer */ - size = frame->registers[size_reg]; /* R2: size */ + device_ptr = frame->locals[device_reg]; /* device pointer */ + buffer_ptr = frame->locals[buffer_reg]; /* R1: buffer pointer */ + size = frame->locals[size_reg]; /* R2: size */ handle = vm->memory[device_ptr + 4]; /* get device handle */ dev = &vm->devices[handle]; @@ -662,7 +662,7 @@ bool step_vm(VM *vm) { device_reg = read_u8(vm, code, vm->pc); vm->pc++; - device_ptr = frame->registers[device_reg]; /* device pointer */ + device_ptr = frame->locals[device_reg]; /* device pointer */ handle = vm->memory[device_ptr + 4]; /* get device handle */ dev = &vm->devices[handle]; @@ -687,9 +687,9 @@ bool step_vm(VM *vm) { args_ptr_reg = read_u8(vm, code, vm->pc); vm->pc++; - device_ptr = frame->registers[device_reg]; /* device pointer */ - cmd = frame->registers[cmd_reg]; /* R1: ioctl command */ - args_ptr = frame->registers[args_ptr_reg]; /* R2: args pointer */ + device_ptr = frame->locals[device_reg]; /* device pointer */ + cmd = frame->locals[cmd_reg]; /* R1: ioctl command */ + args_ptr = frame->locals[args_ptr_reg]; /* R2: args pointer */ handle = vm->memory[device_ptr + 4]; /* get device handle */ dev = &vm->devices[handle]; @@ -740,12 +740,12 @@ bool step_vm(VM *vm) { src1 = read_u8(vm, code, vm->pc); vm->pc++; - value = frame->registers[src1]; + value = frame->locals[src1]; if (value < 0) { value = -value; } - frame->registers[dest] = value; + frame->locals[dest] = value; return true; } case OP_NEG_INT: { @@ -754,8 +754,8 @@ bool step_vm(VM *vm) { src1 = read_u8(vm, code, vm->pc); vm->pc++; - value = frame->registers[src1]; - frame->registers[dest] = -value; + value = frame->locals[src1]; + frame->locals[dest] = -value; return true; } case OP_ADD_NAT: @@ -773,8 +773,8 @@ bool step_vm(VM *vm) { vm->pc++; src2 = read_u8(vm, code, vm->pc); vm->pc++; - frame->registers[dest] = - fixed_mul(frame->registers[src1], frame->registers[src2]); + frame->locals[dest] = + fixed_mul(frame->locals[src1], frame->locals[src2]); return true; } @@ -785,8 +785,8 @@ bool step_vm(VM *vm) { vm->pc++; src2 = read_u8(vm, code, vm->pc); vm->pc++; - frame->registers[dest] = - fixed_div(frame->registers[src1], frame->registers[src2]); + frame->locals[dest] = + fixed_div(frame->locals[src1], frame->locals[src2]); return true; } @@ -797,8 +797,8 @@ bool step_vm(VM *vm) { vm->pc++; src2 = read_u8(vm, code, vm->pc); vm->pc++; - frame->registers[dest] = - fixed_add(frame->registers[src1], frame->registers[src2]); + frame->locals[dest] = + fixed_add(frame->locals[src1], frame->locals[src2]); return true; } @@ -809,8 +809,8 @@ bool step_vm(VM *vm) { vm->pc++; src2 = read_u8(vm, code, vm->pc); vm->pc++; - frame->registers[dest] = - fixed_sub(frame->registers[src1], frame->registers[src2]); + frame->locals[dest] = + fixed_sub(frame->locals[src1], frame->locals[src2]); return true; } case OP_REAL_TO_INT: { @@ -818,9 +818,9 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - value = frame->registers[src1]; + value = frame->locals[src1]; - frame->registers[dest] = fixed_to_int(value); + frame->locals[dest] = fixed_to_int(value); return true; } @@ -829,7 +829,7 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - frame->registers[dest] = int_to_fixed(frame->registers[src1]); + frame->locals[dest] = int_to_fixed(frame->locals[src1]); return true; } case OP_REAL_TO_NAT: { @@ -837,8 +837,8 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - value = frame->registers[src1]; - frame->registers[dest] = fixed_to_int(value); + value = frame->locals[src1]; + frame->locals[dest] = fixed_to_int(value); return true; } case OP_NAT_TO_REAL: { @@ -846,7 +846,7 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - frame->registers[dest] = int_to_fixed(frame->registers[src1]); + frame->locals[dest] = int_to_fixed(frame->locals[src1]); return true; } case OP_JEQ_NAT: { @@ -909,9 +909,9 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - int_to_string(AS_INT(frame->registers[src1]), buffer); + int_to_string(AS_INT(frame->locals[src1]), buffer); ptr = str_alloc(vm, frame, buffer, strlength(buffer)); - frame->registers[dest] = ptr; + frame->locals[dest] = ptr; set_heap_status(vm, dest, true); /* Mark as heap pointer */ return true; } @@ -921,9 +921,9 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - nat_to_string(frame->registers[src1], buffer); + nat_to_string(frame->locals[src1], buffer); ptr = str_alloc(vm, frame, buffer, strlength(buffer)); - frame->registers[dest] = ptr; + frame->locals[dest] = ptr; set_heap_status(vm, dest, true); /* Mark as heap pointer */ return true; } @@ -933,10 +933,10 @@ bool step_vm(VM *vm) { vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; - fixed_to_string(AS_INT(frame->registers[src1]), buffer); + fixed_to_string(AS_INT(frame->locals[src1]), buffer); ptr = str_alloc(vm, frame, buffer, strlength(buffer)); /* copy buffer to dest */ - frame->registers[dest] = ptr; + frame->locals[dest] = ptr; set_heap_status(vm, dest, true); /* Mark as heap pointer */ return true; } @@ -947,9 +947,9 @@ bool step_vm(VM *vm) { src1 = read_u8(vm, code, vm->pc); vm->pc++; - ptr = frame->registers[src1]; + ptr = frame->locals[src1]; length = read_u32(vm, memory, ptr); - frame->registers[dest] = length; + frame->locals[dest] = length; return true; } case OP_STRCAT: { diff --git a/test/add.asm.lisp b/test/add.asm.lisp index 488709f..1c783c7 100644 --- a/test/add.asm.lisp +++ b/test/add.asm.lisp @@ -5,7 +5,7 @@ (call &add ($0 $1) $2) (int-to-string $3 $2) (call &pln ($3) nil) - (halt 0)) + (exit 0)) (label add (add-int $2 $1 $0) diff --git a/test/add.ul.ir b/test/add.ul.ir index 352746b..3c54c04 100644 --- a/test/add.ul.ir +++ b/test/add.ul.ir @@ -26,12 +26,12 @@ function pln (str message is $0) str nl is $3 int nl_length is $4 - load_heap_immediate ts "/dev/term/0" # get terminal device + malloc_immediate "/dev/term/0" -> ts load_immediate 0 -> mode syscall OPEN ts mode -> ts strlen message -> msg_length syscall WRITE ts message msg_length - load_heap_immediate "\n" -> nl + malloc_immediate "\n" -> nl strlen nl -> nl_length syscall WRITE ts nl nl_length return diff --git a/test/fib.asm.lisp b/test/fib.asm.lisp index 3e18589..6004071 100644 --- a/test/fib.asm.lisp +++ b/test/fib.asm.lisp @@ -4,7 +4,7 @@ (call &fib ($0) $0) (int-to-string $1 $0) (call &pln ($1) nil) - (halt 0)) + (exit 0)) (label fib (load-immediate $1 2) (jump-lt-int &base-case $0 $1) diff --git a/test/fib.ul.ir b/test/fib.ul.ir index b35c3fc..03760c8 100644 --- a/test/fib.ul.ir +++ b/test/fib.ul.ir @@ -33,12 +33,12 @@ function pln (str message is $0) str nl is $3 int nl_length is $4 - load_heap_immediate ts "/dev/term/0" # get terminal device + malloc_immediate "/dev/term/0" -> ts load_immediate 0 -> mode syscall OPEN ts mode -> ts strlen message -> msg_length syscall WRITE ts message msg_length - load_heap_immediate "\n" -> nl + malloc_immediate "\n" -> nl strlen nl -> nl_length syscall WRITE ts nl nl_length return diff --git a/test/hello.asm.lisp b/test/hello.asm.lisp index d5e2a58..f14933f 100644 --- a/test/hello.asm.lisp +++ b/test/hello.asm.lisp @@ -2,7 +2,7 @@ (label main (load-immediate $1 &hello-str) ; load hello string ptr (call &pln ($1) nil) - (halt 0)) ; done + (exit 0)) ; done (label pln (load-immediate $1 &terminal-namespace) ; get terminal device (load-immediate $11 0) diff --git a/test/hello.ul.ir b/test/hello.ul.ir index cd2a305..67e729e 100644 --- a/test/hello.ul.ir +++ b/test/hello.ul.ir @@ -1,7 +1,7 @@ function main () str hello is $0 - load_heap_immediate "nuqneH 'u'?" -> hello + malloc_immediate "nuqneH 'u'?" -> hello call pln hello exit 0 @@ -12,12 +12,12 @@ function pln (str message is $0) int nl_length is $4 int mode is $5 - load_heap_immediate "/dev/term/0" -> ts # get terminal device + malloc_immediate "/dev/term/0" -> ts load_immediate 0 -> mode syscall OPEN ts mode -> ts strlen message -> msg_length syscall WRITE ts message msg_length - load_heap_immediate "\n" -> nl + malloc_immediate "\n" -> nl strlen nl -> nl_length syscall WRITE ts nl nl_length return \ No newline at end of file diff --git a/test/loop.asm.lisp b/test/loop.asm.lisp index 6be6c73..7e2b95e 100644 --- a/test/loop.asm.lisp +++ b/test/loop.asm.lisp @@ -27,7 +27,7 @@ (call &pln ($4) nil) (real-to-string $3 $0) (call &pln ($3) nil) - (halt 0)) + (exit 0)) (label pln (load-immediate $1 &terminal-namespace) ; get terminal device (load-immediate $11 0) diff --git a/test/loop.ul.ir b/test/loop.ul.ir index 542f148..88f7660 100644 --- a/test/loop.ul.ir +++ b/test/loop.ul.ir @@ -14,13 +14,13 @@ function main () add_real a $5 -> a add_int i $3 -> i jump_ge_int &loop_body i $2 - load_heap_immediate "/dev/term/0" -> term + malloc_immediate "/dev/term/0" -> term load_immediate 0 -> mode syscall OPEN term mode -> term # Terminal term = open("/dev/term/0", 0); nat b is $1 real_to_nat a -> b - load_heap_immediate "Enter a string:" -> $7 + malloc_immediate "Enter a string:" -> $7 string_length $7 -> $8 syscall WRITE term $7 $8 # print prompt @@ -43,12 +43,12 @@ function pln (str message is $0) str nl is $3 int nl_length is $4 - load_heap_immediate "/dev/term/0" -> ts + malloc_immediate "/dev/term/0" -> ts load_immediate 0 -> mode syscall OPEN ts mode -> ts # get terminal device strlen message -> msg_length syscall WRITE ts message msg_length - load_heap_immediate "\n" -> nl + malloc_immediate "\n" -> nl strlen nl -> nl_length syscall WRITE ts nl nl_length return \ No newline at end of file diff --git a/test/malloc.asm.lisp b/test/malloc.asm.lisp index 382e36a..4f76cf6 100644 --- a/test/malloc.asm.lisp +++ b/test/malloc.asm.lisp @@ -12,7 +12,7 @@ (syscall READ $0 $4 $1) ; read the string (call &pln ($0 $4) nil) ; print the string - (halt 0)) + (exit 0)) (label pln (load-immediate $3 &new-line) (string-length $2 $1) diff --git a/test/malloc.ul.ir b/test/malloc.ul.ir index ea123d7..ef7f66b 100644 --- a/test/malloc.ul.ir +++ b/test/malloc.ul.ir @@ -3,11 +3,11 @@ function main () int mode is $11 str term is $10 - load_heap_immediate "/dev/term/0" -> term + malloc_immediate "/dev/term/0" -> term load_immediate 0 -> mode syscall OPEN term mode -> term # Terminal term = open("/dev/term/0", 0); - load_heap_immediate "Enter a string:" -> $7 + malloc_immediate "Enter a string:" -> $7 string_length $7 -> $8 syscall WRITE term $7 $8 # print prompt @@ -26,11 +26,11 @@ function pln (str message is $0) str nl is $3 int nl_length is $4 - load_heap_immediate "/dev/term/0" -> ts + malloc_immediate "/dev/term/0" -> ts load_immediate 0 -> mode syscall OPEN ts mode -> ts # get terminal device strlen message -> msg_length syscall WRITE ts message msg_length - load_heap_immediate "\n" -> nl + malloc_immediate "\n" -> nl strlen nl -> nl_length syscall WRITE ts nl nl_length diff --git a/test/paint-bw.asm.lisp b/test/paint-bw.asm.lisp index d927e30..81bf808 100644 --- a/test/paint-bw.asm.lisp +++ b/test/paint-bw.asm.lisp @@ -66,8 +66,8 @@ (jump &draw-loop)) - ; Flush and halt - (halt 0)) + ; Flush and exit + (exit 0)) (label set-color-if-clicked ; (click_x, click_y, box_x, box_y, color, box_size) diff --git a/test/paint-bw.ul.ir b/test/paint-bw.ul.ir index dbcf55d..ab40219 100644 --- a/test/paint-bw.ul.ir +++ b/test/paint-bw.ul.ir @@ -94,7 +94,7 @@ function main () jump &draw_loop - # Flush and halt + # Flush and exit exit 0 function set_color_if_clicked (int click_x is $0, int click_y is $1, diff --git a/test/paint.asm.lisp b/test/paint.asm.lisp index 63d3b80..2e946d5 100644 --- a/test/paint.asm.lisp +++ b/test/paint.asm.lisp @@ -153,8 +153,8 @@ (jump &draw-loop)) - ; Flush and halt - (halt 0)) + ; Flush and exit + (exit 0)) (label set-color-if-clicked ; (click_x, click_y, box_x, box_y, color, box_size) diff --git a/test/paint.ul.ir b/test/paint.ul.ir index dbcf55d..ab40219 100644 --- a/test/paint.ul.ir +++ b/test/paint.ul.ir @@ -94,7 +94,7 @@ function main () jump &draw_loop - # Flush and halt + # Flush and exit exit 0 function set_color_if_clicked (int click_x is $0, int click_y is $1, diff --git a/test/simple.asm.lisp b/test/simple.asm.lisp index faa33ff..1cd4d01 100644 --- a/test/simple.asm.lisp +++ b/test/simple.asm.lisp @@ -5,7 +5,7 @@ (add-real $2 $1 $0) (real-to-string $3 $2) (call &pln ($3) nil) - (halt 0)) + (exit 0)) (label pln (load-immediate $1 &terminal-namespace) ; get terminal device (load-immediate $11 0) diff --git a/test/simple.ul.ir b/test/simple.ul.ir index be015d4..8f549d9 100644 --- a/test/simple.ul.ir +++ b/test/simple.ul.ir @@ -20,12 +20,12 @@ function pln (str message is $0) int nl_length is $4 int mode is $5 - load_heap_immediate "/dev/term/0" -> term # get terminal device + malloc_immediate "/dev/term/0" -> term load_immediate 0 -> mode syscall OPEN term mode -> term strlen message -> msg_length syscall WRITE term message msg_length - load_heap_immediate "\n" -> nl + malloc_immediate "\n" -> nl strlen nl -> nl_length syscall WRITE term nl nl_length return diff --git a/test/window.asm.lisp b/test/window.asm.lisp index 0340856..b697ebe 100644 --- a/test/window.asm.lisp +++ b/test/window.asm.lisp @@ -52,7 +52,7 @@ (syscall WRITE $0 $21 $22) ; redraw (jump &draw-loop)) - (halt 0)) + (exit 0)) (label pln (load-immediate $1 &terminal-namespace) ; get terminal device (load-immediate $11 0) diff --git a/test/window.ul.vuir b/test/window.ul.vuir index a7c9aac..8ac09b0 100644 --- a/test/window.ul.vuir +++ b/test/window.ul.vuir @@ -40,21 +40,21 @@ function main () { byte left_down = mouse.left; - if (left_down == 0) continue; + if (left_down == 1) { + nat x = mouse.x; + nat y = mouse.y; - nat x = mouse.x; - nat y = mouse.y; + // Compute start address: y*width + x + nat pixel_pos = y * width; // = y * width + pixel_pos = x + pixel_pos; // += x + pixel_pos = screen_buffer + pixel_pos; // += pixel_offset + nat fat_ptr_size = 4; // need to add offset for fat pointer size + pixel_pos = pixel_pos + fat_ptr_size; - // Compute start address: y*width + x - nat pixel_pos = y * width; // = y * width - pixel_pos = x + pixel_pos; // += x - pixel_pos = screen_buffer + pixel_pos; // += pixel_offset - nat fat_ptr_size = 4; // need to add offset for fat pointer size - pixel_pos = pixel_pos + fat_ptr_size; - - byte color = WHITE; - store_absolute_8(pixel_pos, color); // draw color at screen [x,y] - write(screen, screen_buffer, buffer_size); // redraw + byte color = WHITE; + store_absolute_8(pixel_pos, color); // draw color at screen [x,y] + write(screen, screen_buffer, buffer_size); // redraw + } } exit(0); }