From f901dafa2b90f4dc8d86cd2e5440c8fcaf79ede5 Mon Sep 17 00:00:00 2001 From: zongor Date: Sun, 30 Nov 2025 23:22:25 -0800 Subject: [PATCH] WIP Code generation, 'simple' works --- bench/add.lisp | 4 - bench/fib.lisp | 6 - bench/hello.lisp | 1 - bench/simple.lisp | 1 - src/arch/linux/main.c | 24 - src/tools/assembler/assembler.c | 2120 ++++++++++++++++++++++++++----- src/tools/assembler/assembler.h | 1 + src/tools/assembler/lexer.c | 10 + src/vm/opcodes.h | 15 +- src/vm/vm.c | 578 +++++---- test/add.ul.ir | 20 +- test/fib.ul.ir | 17 +- test/hello.ul.ir | 27 +- test/loop.ul.ir | 30 +- test/malloc.ul.ir | 21 +- test/simple.ul | 5 +- test/simple.ul.ir | 23 +- test/window.ul.ir | 21 +- 18 files changed, 2187 insertions(+), 737 deletions(-) delete mode 100644 bench/add.lisp delete mode 100644 bench/fib.lisp delete mode 100644 bench/hello.lisp delete mode 100644 bench/simple.lisp diff --git a/bench/add.lisp b/bench/add.lisp deleted file mode 100644 index 95e29c0..0000000 --- a/bench/add.lisp +++ /dev/null @@ -1,4 +0,0 @@ -(lambda add-two (a b) - (return (+ a b))) - -(print (to-string (add-two 1 1))) diff --git a/bench/fib.lisp b/bench/fib.lisp deleted file mode 100644 index f73186a..0000000 --- a/bench/fib.lisp +++ /dev/null @@ -1,6 +0,0 @@ -(lambda fib (n) - (if (n < 2) - (return n)) - (return (+ (fib (- n 2)) (fib (- n 1))))) - -(print (fib 36)) \ No newline at end of file diff --git a/bench/hello.lisp b/bench/hello.lisp deleted file mode 100644 index 2856246..0000000 --- a/bench/hello.lisp +++ /dev/null @@ -1 +0,0 @@ -(print "nuqneH 'u'?") \ No newline at end of file diff --git a/bench/simple.lisp b/bench/simple.lisp deleted file mode 100644 index a20fde5..0000000 --- a/bench/simple.lisp +++ /dev/null @@ -1 +0,0 @@ -(print (+ 1.0 2.0)) \ No newline at end of file diff --git a/src/arch/linux/main.c b/src/arch/linux/main.c index 94a4e2a..eef3085 100644 --- a/src/arch/linux/main.c +++ b/src/arch/linux/main.c @@ -163,25 +163,6 @@ bool assembleAndSave(const char *source_file, const char *output_file, VM *vm) { return true; } -bool init_vm(VM *vm) { - vm->memory = (u8 *)malloc(MEMORY_SIZE * sizeof(u8)); - vm->memory_size = MEMORY_SIZE; - - vm->code = (u8 *)malloc(CODE_SIZE * sizeof(u8)); - vm->code_size = CODE_SIZE; - - vm->frames = (Frame *)malloc(FRAMES_SIZE * sizeof(Frame)); - vm->frames_size = FRAMES_SIZE; - - vm->stack = (u32 *)malloc(STACK_SIZE * sizeof(u32)); - vm->stack_size = STACK_SIZE; - - vm->devices = (Device *)malloc(DEVICES_SIZE * sizeof(Device)); - vm->device_size = DEVICES_SIZE; - - return true; -} - i32 main(i32 argc, char *argv[]) { bool dump_rom = false; char *input_file = nil; @@ -212,11 +193,6 @@ i32 main(i32 argc, char *argv[]) { } VM vm = {0}; - if (!init_vm(&vm)) { - printf("vm did not initialize for some reason."); - return 1; - } - bool compilation_success = true; if (input_file) { if (is_rom) { diff --git a/src/tools/assembler/assembler.c b/src/tools/assembler/assembler.c index b45d6f9..3fdc9a9 100644 --- a/src/tools/assembler/assembler.c +++ b/src/tools/assembler/assembler.c @@ -8,19 +8,16 @@ #include #include -void emit_byte(VM *vm, u8 byte) { vm->code[vm->cp++] = byte; } +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; } -SymbolTable *symbol_table_init() { - SymbolTable *table = malloc(sizeof(SymbolTable)); - table->symbols = malloc(16 * sizeof(Symbol)); +void symbol_table_init(SymbolTable *table) { + table->symbols = calloc(16, sizeof(Symbol)); table->count = 0; table->capacity = 16; - return table; } u32 symbol_table_add(SymbolTable *table, Symbol s) { @@ -35,25 +32,64 @@ u32 symbol_table_add(SymbolTable *table, Symbol s) { return index; } -Symbol *symbol_table_lookup(SymbolTable *table, const char *name) { +Symbol *symbol_table_lookup(SymbolTable *table, const char *name, u32 length) { for (u32 i = 0; i < table->count; i++) { - if (streq(table->symbols[i].name, name)) { - return &table->symbols[i]; + if (table->symbols[i].name_length == length) { + if (strleq(table->symbols[i].name, name, length)) { + return &table->symbols[i]; + } } } return nil; } -u32 get_ref(SymbolTable *st, const char *name) { - Symbol *sym = symbol_table_lookup(st, name); +u32 get_ref(SymbolTable *st, const char *name, u32 length) { + Symbol *sym = symbol_table_lookup(st, name, length); if (!sym) { - fprintf(stderr, "Error: Undefined Symbol '%s'\n", name); + fprintf(stderr, "Error: Undefined Symbol '%.*s'\n", length, name); exit(1); return 0; } return sym->ref; } +u32 get_ptr(Token token, SymbolTable *st) { + if (token.type == TOKEN_IDENTIFIER) { + return get_ref(st, token.start, token.length); + } + + if (token.type == TOKEN_LITERAL_INT) { + return atoi(token.start); + } + + if (token.type == TOKEN_LITERAL_NAT) { + char *endptr; + u32 out = (u32)strtoul(token.start, &endptr, 10); + if (endptr == token.start || *endptr != '\0') { + fprintf(stderr, "Invalid decimal literal: '%.*s'\n", token.length, token.start); + exit(1); + } + return out; + } + + fprintf(stderr, "Error: Not a register or symbol '%.*s'\n", token.length, token.start); + exit(1); +} + +u32 get_reg(Token token, SymbolTable *st) { + if (token.type == TOKEN_IDENTIFIER) { + return get_ref(st, token.start, token.length); + } + + if (token.type == TOKEN_BIG_MONEY) { + token = next_token(); + return atoi(token.start); + } + + fprintf(stderr, "Error: Not a register or symbol '%.*s'\n", token.length, token.start); + exit(1); +} + Token next_id_or_reg() { Token token = next_token(); if (token.type == TOKEN_IDENTIFIER) { @@ -75,10 +111,8 @@ Token next_id_or_reg() { Token next_id_or_ptr() { Token token = next_token(); - if (token.type != TOKEN_IDENTIFIER && - token.type != TOKEN_LITERAL_NAT && - token.type != TOKEN_LITERAL_INT && - token.type != TOKEN_LITERAL_REAL) { + if (token.type != TOKEN_IDENTIFIER && token.type != TOKEN_LITERAL_NAT && + token.type != TOKEN_LITERAL_INT && token.type != TOKEN_LITERAL_REAL) { printf("Not an ID or register at line %d: %.*s\n", token.line, token.length, token.start); exit(1); @@ -95,15 +129,6 @@ Token next_token_is(TokenType type) { return token; } -Token next_token_is_either(TokenType type, TokenType type2) { - Token token = next_token(); - if (token.type != type && token.type != type2) { - printf("ERROR at line %d: %.*s\n", token.line, token.length, token.start); - exit(1); - } - return token; -} - /** * Global . */ @@ -159,6 +184,7 @@ bool define_global(VM *vm, SymbolTable *st) { } memcpy(s.name, name.start, name.length); + s.name_length = name.length; u32 addr = vm->mp; s.ref = addr; @@ -226,6 +252,9 @@ bool define_global(VM *vm, SymbolTable *st) { while (i < value.length) { char c = src[i++]; + if (c == '"') { + continue; + } if (c == '\\' && i < value.length) { switch (src[i++]) { case 'n': @@ -245,7 +274,8 @@ bool define_global(VM *vm, SymbolTable *st) { i--; // Rewind for unknown escapes } } - write_u8(vm, memory, addr + 4 + len++, c); + write_u8(vm, memory, addr + 4 + len, c); + len++; } u32 size = len + 5; // 4 (len) + dst_len + 1 (null) @@ -338,6 +368,8 @@ void define_var(SymbolTable *st, Token regType) { } memcpy(s.name, name.start, name.length); + s.name[name.length] = '\0'; + s.name_length = name.length; next_token_is(TOKEN_BIG_MONEY); @@ -361,13 +393,14 @@ void define_function(VM *vm, SymbolTable *st) { exit(1); } memcpy(s.name, name.start, name.length); + s.name[name.length] = '\0'; + s.name_length = name.length; next_token_is(TOKEN_LPAREN); Token next = next_token(); while (next.type != TOKEN_RPAREN) { define_var(st, next); - next = next_token(); if (next.type == TOKEN_COMMA) { next = next_token(); @@ -379,7 +412,7 @@ void define_function(VM *vm, SymbolTable *st) { exit(1); } } - s.ref = vm->pc; + s.ref = vm->cp; symbol_table_add(st, s); } @@ -398,8 +431,9 @@ void define_branch(VM *vm, SymbolTable *st) { exit(1); } memcpy(s.name, name.start, name.length); + s.name_length = name.length; - s.ref = vm->pc; + s.ref = vm->cp; symbol_table_add(st, s); } @@ -416,8 +450,9 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) { exit(1); } - printf("Line %d [%s]: %.*s\n", token.line, token_type_to_string(token.type), - token.length, token.start); + printf("Line %d [%s]: %.*s cp=%d mp=%d\n", token.line, + token_type_to_string(token.type), token.length, token.start, vm->cp, + vm->mp); if (token.type == TOKEN_KEYWORD_GLOBAL) { define_global(vm, st); @@ -434,7 +469,7 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) { token.type == TOKEN_TYPE_U8 || token.type == TOKEN_TYPE_U16 || token.type == TOKEN_TYPE_NAT || token.type == TOKEN_TYPE_REAL || token.type == TOKEN_TYPE_STR || token.type == TOKEN_TYPE_BOOL) { - define_var(st, token); + define_var(st, token); next_token_is(TOKEN_SEMICOLON); continue; } @@ -447,16 +482,16 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) { } if (token.type == TOKEN_KEYWORD_RETURN) { - vm->pc++; + vm->cp++; Token next = next_token(); if (next.type == TOKEN_SEMICOLON) { /* put 0xFF as return register */ - vm->pc++; + vm->cp++; continue; } - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); continue; } @@ -464,1047 +499,1043 @@ void build_symbol_table(VM *vm, char *source, SymbolTable *st) { if (token.type == TOKEN_IDENTIFIER) { // check to see if it is an opcode first if (strleq(token.start, "exit", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "call", token.length)) { - vm->pc++; + vm->cp++; next_token_is(TOKEN_IDENTIFIER); - vm->pc += 4; - vm->pc++; /* number of args (implied) */ - - Token next = next_token(); - while (next.type != TOKEN_ARROW_RIGHT) { - vm->pc++; - next = next_token(); - } - /* return type */ - next = next_token(); - vm->pc++; /* we emit a value regardless, a void is register 255 */ - if (next.type == TOKEN_SEMICOLON) { - /* exit early because no return type */ - continue; - } - /* if it is not void, then it was the value */ - next_token_is(TOKEN_SEMICOLON); - } else if (strleq(token.start, "syscall", token.length)) { - vm->pc++; - - next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; Token next = next_token(); while (next.type != TOKEN_SEMICOLON) { if (next.type != TOKEN_ARROW_RIGHT) { - vm->pc++; + vm->cp++; + } + next = next_token(); + } + + vm->cp++; /* number of args (implied) */ + + } else if (strleq(token.start, "syscall", token.length)) { + vm->cp++; + + next_token_is(TOKEN_IDENTIFIER); + + vm->cp += 4; + + Token next = next_token(); + while (next.type != TOKEN_SEMICOLON) { + if (next.type != TOKEN_ARROW_RIGHT) { + vm->cp++; } next = next_token(); } } else if (strleq(token.start, "load_immediate", token.length)) { - vm->pc++; + vm->cp++; - next_id_or_ptr(); - vm->pc += 4; + next_token(); // literal + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "load_address", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; - next_token_is(TOKEN_SEMICOLON); + next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "malloc", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "memset_8", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "memset_16", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "memset_32", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "load_offset_8", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "load_offset_16", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "load_offset_32", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "load_indirect_8", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "load_indirect_16", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "load_indirect_32", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "load_absolute_8", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "load_absolute_16", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "load_absolute_32", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "store_absolute_8", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "store_absolute_16", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "store_absolute_32", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "store_indirect_8", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "store_indirect_16", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "store_indirect_32", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "store_offset_8", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); /* src1 */ - vm->pc++; + vm->cp++; next_token_is(TOKEN_LITERAL_NAT); /* offset */ - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); /* dest */ - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "store_offset_16", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); /* src1 */ - vm->pc++; + vm->cp++; next_token_is(TOKEN_LITERAL_NAT); /* offset */ - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); /* dest */ - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "store_offset_32", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); /* src1 */ - vm->pc++; + vm->cp++; next_token_is(TOKEN_LITERAL_NAT); /* offset */ - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); /* dest */ - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "register_move", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "add_int", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "sub_int", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "mul_int", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "div_int", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "abs_int", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "neg_int", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "add_nat", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "sub_nat", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "mul_nat", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "div_nat", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "abs_nat", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "neg_nat", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "add_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "sub_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "mul_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "div_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "abs_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "neg_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "int_to_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "nat_to_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "real_to_int", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "real_to_nat", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "bit_shift_left", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "bit_shift_right", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "bit_shift_r_ext", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "bit_and", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "bit_or", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "bit_xor", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_if_flag", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_eq_int", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_neq_int", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_gt_int", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_lt_int", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_le_int", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_ge_int", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_eq_nat", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_neq_nat", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_gt_nat", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_lt_nat", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_le_nat", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_ge_nat", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_eq_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_neq_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_ge_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_gt_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_lt_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "jump_le_real", token.length)) { - vm->pc++; + vm->cp++; next_id_or_ptr(); - vm->pc += 4; + vm->cp += 4; next_id_or_reg(); - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "string_length", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "int_to_string", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "nat_to_string", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "real_to_string", token.length)) { - vm->pc++; + vm->cp++; next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_ARROW_RIGHT); next_id_or_reg(); - vm->pc++; + vm->cp++; next_token_is(TOKEN_SEMICOLON); } else if (strleq(token.start, "string_eq", token.length)) { @@ -1540,8 +1571,9 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { break; } if (token.type != TOKEN_EOF) { - printf("[Generate Bytecode] Line %d [%s]: %.*s\n", token.line, - token_type_to_string(token.type), token.length, token.start); + printf("[Generate Bytecode cp=%d mp=%d ] Line %d [%s]: %.*s\n", vm->cp, + vm->mp, token.line, token_type_to_string(token.type), token.length, + token.start); if (token.type == TOKEN_KEYWORD_GLOBAL) { // ignore, already processed @@ -1583,20 +1615,1410 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { } if (token.type == TOKEN_KEYWORD_RETURN) { - vm->pc++; + emit_byte(vm, OP_RETURN); + vm->cp++; Token next = next_token(); if (next.type == TOKEN_SEMICOLON) { /* put 0xFF as return register */ - emit_u8(vm, 0xFF); - vm->pc++; + emit_byte(vm, 0xFF); + vm->cp++; continue; } - vm->pc++; + u32 reg = get_reg(next, st); + emit_byte(vm, reg); + vm->cp++; next_token_is(TOKEN_SEMICOLON); continue; } + + if (token.type == TOKEN_IDENTIFIER) { + // check to see if it is an opcode first + if (strleq(token.start, "exit", token.length)) { + + emit_byte(vm, OP_EXIT); + vm->cp++; + + Token next = next_token(); + u32 ptr = get_ptr(next, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "call", token.length)) { + + emit_byte(vm, OP_CALL); + vm->cp++; + + Token id = next_token_is(TOKEN_IDENTIFIER); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + bool has_return = false; + u8 arg_count = 0; + u32 arg_pos = vm->cp++; + + Token next = next_token(); + while (next.type != TOKEN_SEMICOLON) { + if (next.type != TOKEN_ARROW_RIGHT) { + u8 arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + arg_count++; + } else { + has_return = true; + } + next = next_token(); + } + + /* patch number of args */ + vm->code[arg_pos] = arg_count; + + if (!has_return) { + vm->cp++; + emit_byte(vm, 255); + continue; + } + } else if (strleq(token.start, "syscall", token.length)) { + + emit_byte(vm, OP_SYSCALL); + vm->cp++; + + Token next = next_token(); + + u32 syscall_id = 0; + const char *syscall_name = next.start; + if (strleq(syscall_name, "EXIT", next.length)) + syscall_id = SYSCALL_EXIT; + else if (strleq(syscall_name, "OPEN", next.length)) + syscall_id = SYSCALL_DEVICE_OPEN; + else if (strleq(syscall_name, "READ", next.length)) + syscall_id = SYSCALL_DEVICE_READ; + else if (strleq(syscall_name, "WRITE", next.length)) + syscall_id = SYSCALL_DEVICE_WRITE; + else if (strleq(syscall_name, "CLOSE", next.length)) + syscall_id = SYSCALL_DEVICE_CLOSE; + else if (strleq(syscall_name, "IOCTL", next.length)) + syscall_id = SYSCALL_DEVICE_IOCTL; + else if (strleq(syscall_name, "REFRESH", next.length)) + syscall_id = SYSCALL_DEVICE_REFRESH; + + emit_u32(vm, syscall_id); + vm->cp += 4; + + next = next_token(); + while (next.type != TOKEN_SEMICOLON) { + if (next.type != TOKEN_ARROW_RIGHT) { + u8 arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + } + next = next_token(); + } + + } else if (strleq(token.start, "load_immediate", token.length)) { + + emit_byte(vm, OP_LOAD_IMM); + vm->cp++; + + Token value = next_token(); + switch (value.type) { + case TOKEN_KEYWORD_TRUE: { + emit_u32(vm, 1); + break; + } + case TOKEN_KEYWORD_FALSE: { + emit_u32(vm, 0); + break; + } + case TOKEN_LITERAL_INT: { + i32 out = atoi(value.start); + emit_u32(vm, out); + break; + } + case TOKEN_LITERAL_NAT: { + char *endptr; + u32 out = (u32)strtoul(value.start, &endptr, 10); + if (endptr == value.start || *endptr != '\0') { + fprintf(stderr, "Invalid 'real' number: '%.*s'\n", token.length, token.start); + exit(1); + } + emit_u32(vm, out); + break; + } + case TOKEN_LITERAL_REAL: { + fixed_t out = float_to_fixed(atof(value.start)); + emit_u32(vm, out); + break; + } + default:{ + fprintf(stderr, "Unknown immediate: '%.*s'\n", token.length, token.start); + exit(1); + } + } + + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_address", token.length)) { + emit_byte(vm, OP_LOAD_IMM); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "malloc", token.length)) { + emit_byte(vm, OP_MALLOC); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "memset_8", token.length)) { + emit_byte(vm, OP_MEMSET_8); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "memset_16", token.length)) { + emit_byte(vm, OP_MEMSET_16); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "memset_32", token.length)) { + emit_byte(vm, OP_MEMSET_32); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_offset_8", token.length)) { + emit_byte(vm, OP_LOAD_OFF_8); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_offset_16", token.length)) { + emit_byte(vm, OP_LOAD_OFF_16); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_offset_32", token.length)) { + emit_byte(vm, OP_LOAD_OFF_32); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_indirect_8", token.length)) { + emit_byte(vm, OP_LOAD_IND_8); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_indirect_16", token.length)) { + emit_byte(vm, OP_LOAD_IND_16); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_indirect_32", token.length)) { + emit_byte(vm, OP_LOAD_IND_32); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_absolute_8", token.length)) { + emit_byte(vm, OP_LOAD_ABS_8); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_absolute_16", token.length)) { + emit_byte(vm, OP_LOAD_ABS_16); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "load_absolute_32", token.length)) { + emit_byte(vm, OP_LOAD_ABS_32); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_absolute_8", token.length)) { + emit_byte(vm, OP_STORE_ABS_8); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_absolute_16", token.length)) { + emit_byte(vm, OP_STORE_ABS_16); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_absolute_32", token.length)) { + emit_byte(vm, OP_STORE_ABS_32); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_indirect_8", token.length)) { + emit_byte(vm, OP_STORE_IND_8); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_indirect_16", token.length)) { + emit_byte(vm, OP_STORE_IND_16); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_indirect_32", token.length)) { + emit_byte(vm, OP_STORE_IND_32); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_ARROW_RIGHT); + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_offset_8", token.length)) { + emit_byte(vm, OP_STORE_OFF_8); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_offset_16", token.length)) { + emit_byte(vm, OP_STORE_OFF_16); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "store_offset_32", token.length)) { + emit_byte(vm, OP_STORE_OFF_32); + vm->cp++; + + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_ARROW_RIGHT); + + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "register_move", token.length)) { + emit_byte(vm, OP_REG_MOV); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "add_int", token.length)) { + emit_byte(vm, OP_ADD_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "sub_int", token.length)) { + emit_byte(vm, OP_SUB_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "mul_int", token.length)) { + emit_byte(vm, OP_MUL_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "div_int", token.length)) { + emit_byte(vm, OP_DIV_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "abs_int", token.length)) { + emit_byte(vm, OP_ABS_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "neg_int", token.length)) { + emit_byte(vm, OP_NEG_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "add_nat", token.length)) { + emit_byte(vm, OP_ADD_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "sub_nat", token.length)) { + emit_byte(vm, OP_SUB_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "mul_nat", token.length)) { + emit_byte(vm, OP_MUL_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "div_nat", token.length)) { + emit_byte(vm, OP_DIV_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "abs_nat", token.length)) { + emit_byte(vm, OP_ABS_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "neg_nat", token.length)) { + emit_byte(vm, OP_NEG_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "add_real", token.length)) { + emit_byte(vm, OP_ADD_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON);; + } else if (strleq(token.start, "sub_real", token.length)) { + emit_byte(vm, OP_SUB_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "mul_real", token.length)) { + emit_byte(vm, OP_MUL_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "div_real", token.length)) { + emit_byte(vm, OP_DIV_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "abs_real", token.length)) { + emit_byte(vm, OP_ABS_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "neg_real", token.length)) { + emit_byte(vm, OP_NEG_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "int_to_real", token.length)) { + emit_byte(vm, OP_INT_TO_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "nat_to_real", token.length)) { + emit_byte(vm, OP_NAT_TO_REAL); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "real_to_int", token.length)) { + emit_byte(vm, OP_REAL_TO_INT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "real_to_nat", token.length)) { + emit_byte(vm, OP_REAL_TO_NAT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "bit_shift_left", token.length)) { + emit_byte(vm, OP_BIT_SHIFT_LEFT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "bit_shift_right", token.length)) { + emit_byte(vm, OP_BIT_SHIFT_RIGHT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "bit_shift_r_ext", token.length)) { + emit_byte(vm, OP_BIT_SHIFT_R_EXT); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "bit_and", token.length)) { + emit_byte(vm, OP_BAND); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "bit_or", token.length)) { + emit_byte(vm, OP_BOR); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "bit_xor", token.length)) { + emit_byte(vm, OP_BXOR); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + Token next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + next = next_token(); + arg = get_reg(next, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump", token.length)) { + emit_byte(vm, OP_JMP); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_if_flag", token.length)) { + emit_byte(vm, OP_JMPF); + vm->cp++; + + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_eq_int", token.length)) { + emit_byte(vm, OP_JEQ_INT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_neq_int", token.length)) { + emit_byte(vm, OP_JNEQ_INT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_gt_int", token.length)) { + emit_byte(vm, OP_JGT_INT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_lt_int", token.length)) { + emit_byte(vm, OP_JLT_INT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_le_int", token.length)) { + emit_byte(vm, OP_JLE_INT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_ge_int", token.length)) { + emit_byte(vm, OP_JGE_INT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_eq_nat", token.length)) { + emit_byte(vm, OP_JEQ_NAT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_neq_nat", token.length)) { + emit_byte(vm, OP_JNEQ_NAT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_gt_nat", token.length)) { + emit_byte(vm, OP_JGT_NAT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_lt_nat", token.length)) { + emit_byte(vm, OP_JLT_NAT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_le_nat", token.length)) { + emit_byte(vm, OP_JLE_NAT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_ge_nat", token.length)) { + emit_byte(vm, OP_JGE_NAT); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_eq_real", token.length)) { + emit_byte(vm, OP_JEQ_REAL); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_neq_real", token.length)) { + emit_byte(vm, OP_JNEQ_REAL); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_ge_real", token.length)) { + emit_byte(vm, OP_JGE_REAL); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_gt_real", token.length)) { + emit_byte(vm, OP_JGT_REAL); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_lt_real", token.length)) { + emit_byte(vm, OP_JLT_REAL); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "jump_le_real", token.length)) { + emit_byte(vm, OP_JLE_REAL); + vm->cp++; + Token id = next_token(); + u32 ptr = get_ptr(id, st); + emit_u32(vm, ptr); + vm->cp += 4; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "string_length", token.length)) { + emit_byte(vm, OP_STRLEN); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "int_to_string", token.length)) { + emit_byte(vm, OP_INT_TO_STRING); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "nat_to_string", token.length)) { + emit_byte(vm, OP_NAT_TO_STRING); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON); + } else if (strleq(token.start, "real_to_string", token.length)) { + emit_byte(vm, OP_REAL_TO_STRING); + vm->cp++; + Token reg = next_token(); + u8 arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_ARROW_RIGHT); + reg = next_token(); + arg = get_reg(reg, st); + emit_byte(vm, arg); + vm->cp++; + next_token_is(TOKEN_SEMICOLON);; + } else if (strleq(token.start, "string_eq", token.length)) { + } else if (strleq(token.start, "string_concat", token.length)) { + } else if (strleq(token.start, "string_get_char", token.length)) { + } else if (strleq(token.start, "string_find_char", token.length)) { + } else if (strleq(token.start, "string_slice", token.length)) { + } else if (strleq(token.start, "string_to_int", token.length)) { + } else if (strleq(token.start, "string_to_nat", token.length)) { + } else if (strleq(token.start, "string_to_real", token.length)) { + } else { + // some other identifier + printf("Unknown id at line %d: %.*s\n", token.line, token.length, + token.start); + exit(1); + } + } } } while (token.type != TOKEN_EOF); } @@ -1605,10 +3027,10 @@ void emit_bytecode(VM *vm, char *source, SymbolTable *st) { * Emit bytecode to the VM from the source string. */ void assemble(VM *vm, char *source) { - SymbolTable *st = symbol_table_init(); - build_symbol_table(vm, source, st); - vm->pc = 0; /* actuall start emitting code */ - emit_bytecode(vm, source, st); - free(st->symbols); - free(st); + SymbolTable st = {0}; + symbol_table_init(&st); + build_symbol_table(vm, source, &st); + vm->cp = 0; /* actuall start emitting code */ + emit_bytecode(vm, source, &st); + free(st.symbols); } diff --git a/src/tools/assembler/assembler.h b/src/tools/assembler/assembler.h index 657dd40..107f2be 100644 --- a/src/tools/assembler/assembler.h +++ b/src/tools/assembler/assembler.h @@ -30,6 +30,7 @@ typedef struct symbol_tab_s SymbolTable; #define MAX_SYMBOL_NAME_LENGTH 64 struct symbol_s { char name[MAX_SYMBOL_NAME_LENGTH]; + u8 name_length; SymbolType type; ScopeType scope; u32 ref; // vm->mp if global, vm->pc local, register if var diff --git a/src/tools/assembler/lexer.c b/src/tools/assembler/lexer.c index d926380..58a2078 100644 --- a/src/tools/assembler/lexer.c +++ b/src/tools/assembler/lexer.c @@ -276,6 +276,16 @@ static TokenType identifierType() { } } break; + case 'b': + if (lexer.current - lexer.start > 1) { + switch (lexer.start[1]) { + case 'y': + return check_keyword(2, 2, "te", TOKEN_TYPE_U8); + case 'o': + return check_keyword(2, 2, "ol", TOKEN_TYPE_U8); + } + } + break; case 'g': return check_keyword(1, 5, "lobal", TOKEN_KEYWORD_GLOBAL); case 'l': diff --git a/src/vm/opcodes.h b/src/vm/opcodes.h index 91d2b57..dbb7b73 100644 --- a/src/vm/opcodes.h +++ b/src/vm/opcodes.h @@ -150,16 +150,11 @@ typedef struct vm_s { u32 mp; /* memory pointer (last allocated value) */ u32 dc; /* device count */ i32 flag; /* flag (temporary results like SYSCALL status) */ - Frame *frames; /* function call frames */ - u32 frames_size; /* max frames */ - u32 *stack; /* main stack */ - u32 stack_size; /* max stack */ - Device *devices; /* device definitions */ - u32 device_size; /* max devices */ - u8 *code; /* code block */ - u32 code_size; /* max code size */ - u8 *memory; /* memory block */ - u32 memory_size; /* max memory size */ + Frame frames[FRAMES_SIZE]; /* function call frames */ + u32 stack[STACK_SIZE]; /* main stack */ + Device devices[DEVICES_SIZE]; /* device definitions */ + u8 code[CODE_SIZE]; /* code block */ + u8 memory[MEMORY_SIZE]; /* memory block */ } VM; /** diff --git a/src/vm/vm.c b/src/vm/vm.c index cca75e5..45c78af 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -27,26 +27,28 @@ #define MATH_OP(type, op) \ do { \ + u8 src1, src2, dest; \ u32 *regs = frame->locals; \ - dest = read_u8(vm, code, vm->pc); \ - vm->pc++; \ src1 = read_u8(vm, code, vm->pc); \ vm->pc++; \ src2 = read_u8(vm, code, vm->pc); \ vm->pc++; \ + dest = read_u8(vm, code, vm->pc); \ + vm->pc++; \ regs[dest] = (type)regs[src1] op(type) regs[src2]; \ return true; \ } while (0) #define BIT_OP(op) \ do { \ + u8 src1, src2, dest; \ u32 *regs = frame->locals; \ - dest = read_u8(vm, code, vm->pc); \ - vm->pc++; \ src1 = read_u8(vm, code, vm->pc); \ vm->pc++; \ src2 = read_u8(vm, code, vm->pc); \ vm->pc++; \ + dest = read_u8(vm, code, vm->pc); \ + vm->pc++; \ regs[dest] = regs[src1] op regs[src2]; \ return true; \ } while (0) @@ -83,14 +85,9 @@ u32 str_alloc(VM *vm, Frame *frame, const char *str, u32 length) { * Step to the next opcode in the vm. */ bool step_vm(VM *vm) { - u16 opcode, dest, src1, src2; - u32 v, ptr; - i32 value; - Frame *frame; - /* Get current instruction & Advance to next instruction */ - opcode = vm->code[vm->pc++]; - frame = &vm->frames[vm->fp]; + u8 opcode = vm->code[vm->pc++]; + Frame *frame = &vm->frames[vm->fp]; switch (opcode) { case OP_EXIT: { @@ -177,12 +174,23 @@ bool step_vm(VM *vm) { vm->fp--; return true; } - case OP_MALLOC: { - u32 size; + case OP_LOAD_IMM: { + u32 v; + u8 dest; + v = read_u32(vm, code, vm->pc); + vm->pc += 4; dest = read_u8(vm, code, vm->pc); vm->pc++; + frame->locals[dest] = v; + return true; + } + case OP_MALLOC: { + u8 src1, dest; + u32 size; src1 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; frame->locals[dest] = vm->mp; size = frame->locals[src1]; write_u32(vm, memory, vm->mp, size); @@ -192,9 +200,9 @@ bool step_vm(VM *vm) { } case OP_MEMSET_32: { u32 i, start, end; - u8 dest_reg = read_u8(vm, code, vm->pc++); u8 value_reg = read_u8(vm, code, vm->pc++); u8 count_reg = read_u8(vm, code, vm->pc++); + u8 dest_reg = read_u8(vm, code, vm->pc++); u32 dest = frame->locals[dest_reg]; u32 value = frame->locals[value_reg]; @@ -220,12 +228,251 @@ bool step_vm(VM *vm) { frame->locals[0] = dest; vm->flag = 1; return true; + } + case OP_LOAD_ABS_32: { + u32 v, ptr; + u8 dest; + ptr = read_u32(vm, code, vm->pc); + vm->pc += 4; + v = read_u32(vm, memory, ptr); + dest = read_u8(vm, code, vm->pc); + vm->pc++; + frame->locals[dest] = v; + return true; + } + case OP_LOAD_ABS_16: { + u32 v, ptr; + u8 dest; + ptr = read_u32(vm, code, vm->pc); + vm->pc += 4; + v = read_u16(vm, memory, ptr); + dest = read_u8(vm, code, vm->pc); + vm->pc++; + frame->locals[dest] = v; + return true; + } + case OP_LOAD_ABS_8: { + u32 v, ptr; + u8 dest; + ptr = read_u32(vm, code, vm->pc); + vm->pc += 4; + v = read_u8(vm, memory, ptr); + dest = read_u8(vm, code, vm->pc); + vm->pc++; + frame->locals[dest] = v; + return true; + } + case OP_LOAD_IND_32: { + u32 v, ptr; + u8 dest, src1; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + v = frame->locals[src1]; + ptr = read_u32(vm, memory, v); + frame->locals[dest] = ptr; + return true; + } + case OP_LOAD_IND_16: { + u32 v; + u8 dest, src1; + u16 v16; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + v = frame->locals[src1]; + v16 = read_u16(vm, memory, v); + frame->locals[dest] = v16; + return true; + } + case OP_LOAD_IND_8: { + u32 v; + u8 dest, src1; + u8 v8; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + v = frame->locals[src1]; + v8 = read_u8(vm, memory, v); + frame->locals[dest] = v8; + return true; + } + case OP_LOAD_OFF_8: { + u32 v; + u8 dest, src1; + u32 offset; + u8 v8; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + offset = read_u32(vm, code, vm->pc); + vm->pc += 4; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + v = frame->locals[src1]; + v8 = read_u8(vm, memory, (v + offset)); + frame->locals[dest] = v8; + return true; + } + case OP_LOAD_OFF_16: { + u32 v; + u8 dest, src1; + u32 offset; + u16 v16; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + offset = read_u32(vm, code, vm->pc); + vm->pc += 4; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + v = frame->locals[src1]; + v16 = read_u16(vm, memory, (v + offset)); + frame->locals[dest] = v16; + return true; + } + case OP_LOAD_OFF_32: { + u32 v, ptr; + u8 dest, src1; + u32 offset; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + offset = read_u32(vm, code, vm->pc); + vm->pc += 4; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + v = frame->locals[src1]; + ptr = read_u32(vm, memory, (v + offset)); + frame->locals[dest] = ptr; + return true; + } + case OP_STORE_ABS_32: { + u32 v, ptr; + u8 dest, src1; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + v = frame->locals[src1]; + ptr = frame->locals[dest]; + write_u32(vm, memory, ptr, v); + return true; + } + case OP_STORE_ABS_16: { + u32 v, ptr; + u8 dest, src1; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + v = frame->locals[src1]; + ptr = frame->locals[dest]; + write_u16(vm, memory, ptr, v); + return true; + } + case OP_STORE_ABS_8: { + u32 v, ptr; + u8 dest, src1; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + v = frame->locals[src1]; + ptr = frame->locals[dest]; + write_u8(vm, memory, ptr, v); + return true; + } + case OP_STORE_IND_32: { + u32 v, ptr; + u8 dest, src1; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + ptr = frame->locals[dest]; + v = frame->locals[src1]; + write_u32(vm, memory, ptr, v); + return true; + } + case OP_STORE_IND_16: { + u32 ptr; + u8 dest, src1; + u16 v16; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + ptr = frame->locals[dest]; + v16 = frame->locals[src1]; + write_u16(vm, memory, ptr, v16); + return true; + } + case OP_STORE_IND_8: { + u32 ptr; + u8 dest, src1; + u8 v8; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + ptr = frame->locals[dest]; + v8 = frame->locals[src1]; + write_u8(vm, memory, ptr, v8); + return true; + } + case OP_STORE_OFF_8: { + u32 ptr; + u8 dest, src1; + u32 offset; + u8 v8; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + offset = read_u32(vm, code, vm->pc); + vm->pc += 4; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + ptr = frame->locals[dest]; + v8 = frame->locals[src1]; + write_u8(vm, memory, (ptr + offset), v8); + return true; + } + case OP_STORE_OFF_16: { + u32 ptr; + u8 dest, src1; + u32 offset; + u16 v16; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + offset = read_u32(vm, code, vm->pc); + vm->pc += 4; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + ptr = frame->locals[dest]; + v16 = frame->locals[src1]; + write_u16(vm, memory, (ptr + offset), v16); + return true; + } + case OP_STORE_OFF_32: { + u32 v, ptr; + u8 dest, src1; + u32 offset; + src1 = read_u8(vm, code, vm->pc); + vm->pc++; + offset = read_u32(vm, code, vm->pc); + vm->pc += 4; + dest = read_u8(vm, code, vm->pc); + vm->pc++; + ptr = frame->locals[dest]; + v = frame->locals[src1]; + write_u32(vm, memory, (ptr + offset), v); + return true; } case OP_MEMSET_16: { u32 i, start, end; - u8 dest_reg = read_u8(vm, code, vm->pc++); u8 value_reg = read_u8(vm, code, vm->pc++); u8 count_reg = read_u8(vm, code, vm->pc++); + u8 dest_reg = read_u8(vm, code, vm->pc++); u32 dest = frame->locals[dest_reg]; u16 value = (u16)(frame->locals[value_reg]); @@ -254,9 +501,9 @@ bool step_vm(VM *vm) { } case OP_MEMSET_8: { u32 i, start, end; - u8 dest_reg = read_u8(vm, code, vm->pc++); u8 value_reg = read_u8(vm, code, vm->pc++); u8 count_reg = read_u8(vm, code, vm->pc++); + u8 dest_reg = read_u8(vm, code, vm->pc++); u32 dest = frame->locals[dest_reg]; u8 value = (u8)(frame->locals[value_reg]); @@ -282,223 +529,13 @@ bool step_vm(VM *vm) { frame->locals[0] = dest; vm->flag = 1; return true; - } - case OP_LOAD_IMM: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; - v = read_u32(vm, code, vm->pc); - vm->pc += 4; - frame->locals[dest] = v; - return true; - } - case OP_LOAD_ABS_32: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; - ptr = read_u32(vm, code, vm->pc); - vm->pc += 4; - v = read_u32(vm, memory, ptr); - frame->locals[dest] = v; - return true; - } - case OP_LOAD_ABS_16: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; - ptr = read_u32(vm, code, vm->pc); - vm->pc += 4; - v = read_u16(vm, memory, ptr); - frame->locals[dest] = v; - return true; - } - case OP_LOAD_ABS_8: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; - ptr = read_u32(vm, code, vm->pc); - vm->pc += 4; - v = read_u8(vm, memory, ptr); - frame->locals[dest] = v; - return true; - } - case OP_LOAD_IND_32: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - v = frame->locals[src1]; - ptr = read_u32(vm, memory, v); - frame->locals[dest] = ptr; - return true; - } - case OP_LOAD_IND_16: { - u16 v16; - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - v = frame->locals[src1]; - v16 = read_u16(vm, memory, v); - frame->locals[dest] = v16; - return true; - } - case OP_LOAD_IND_8: { - u8 v8; - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - v = frame->locals[src1]; - v8 = read_u8(vm, memory, v); - frame->locals[dest] = v8; - return true; - } - case OP_LOAD_OFF_8: { - u32 offset; - u8 v8; - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - offset = read_u32(vm, code, vm->pc); - vm->pc += 4; - v = frame->locals[src1]; - v8 = read_u8(vm, memory, (v + offset)); - frame->locals[dest] = v8; - return true; - } - case OP_LOAD_OFF_16: { - u32 offset; - u16 v16; - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - offset = read_u32(vm, code, vm->pc); - vm->pc += 4; - v = frame->locals[src1]; - v16 = read_u16(vm, memory, (v + offset)); - frame->locals[dest] = v16; - return true; - } - case OP_LOAD_OFF_32: { - u32 offset; - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - offset = read_u32(vm, code, vm->pc); - vm->pc += 4; - v = frame->locals[src1]; - ptr = read_u32(vm, memory, (v + offset)); - frame->locals[dest] = ptr; - return true; - } - case OP_STORE_ABS_32: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - v = frame->locals[src1]; - ptr = frame->locals[dest]; - write_u32(vm, memory, ptr, v); - return true; - } - case OP_STORE_ABS_16: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - v = frame->locals[src1]; - ptr = frame->locals[dest]; - write_u16(vm, memory, ptr, v); - return true; - } - case OP_STORE_ABS_8: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - v = frame->locals[src1]; - ptr = frame->locals[dest]; - write_u8(vm, memory, ptr, v); - return true; - } - case OP_STORE_IND_32: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - ptr = frame->locals[dest]; - v = frame->locals[src1]; - write_u32(vm, memory, ptr, v); - return true; - } - case OP_STORE_IND_16: { - u16 v16; - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - ptr = frame->locals[dest]; - v16 = frame->locals[src1]; - write_u16(vm, memory, ptr, v16); - return true; - } - case OP_STORE_IND_8: { - u8 v8; - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - ptr = frame->locals[dest]; - v8 = frame->locals[src1]; - write_u8(vm, memory, ptr, v8); - return true; - } - case OP_STORE_OFF_8: { - u32 offset; - u8 v8; - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - offset = read_u32(vm, code, vm->pc); - vm->pc += 4; - ptr = frame->locals[dest]; - v8 = frame->locals[src1]; - write_u8(vm, memory, (ptr + offset), v8); - return true; - } - case OP_STORE_OFF_16: { - u32 offset; - u16 v16; - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - offset = read_u32(vm, code, vm->pc); - vm->pc += 4; - ptr = frame->locals[dest]; - v16 = frame->locals[src1]; - write_u16(vm, memory, (ptr + offset), v16); - return true; - } - case OP_STORE_OFF_32: { - u32 offset; - dest = read_u8(vm, code, vm->pc); - vm->pc++; - src1 = read_u8(vm, code, vm->pc); - vm->pc++; - offset = read_u32(vm, code, vm->pc); - vm->pc += 4; - ptr = frame->locals[dest]; - v = frame->locals[src1]; - write_u32(vm, memory, (ptr + offset), v); - return true; - } + } case OP_REG_MOV: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; + u8 dest, src1; src1 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; frame->locals[dest] = frame->locals[src1]; if (is_heap_value(vm, src1)) { @@ -532,12 +569,12 @@ bool step_vm(VM *vm) { Device *dev; u32 path_ptr, mode, device_ptr; u8 path_reg, mode_reg, dest_reg; - dest_reg = read_u8(vm, code, vm->pc); - vm->pc++; path_reg = read_u8(vm, code, vm->pc); vm->pc++; mode_reg = read_u8(vm, code, vm->pc); vm->pc++; + dest_reg = read_u8(vm, code, vm->pc); + vm->pc++; path_ptr = frame->locals[path_reg]; mode = frame->locals[mode_reg]; @@ -715,10 +752,12 @@ bool step_vm(VM *vm) { case OP_DIV_INT: MATH_OP(i32, /); case OP_ABS_INT: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; + u8 dest, src1; + i32 value; src1 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; value = frame->locals[src1]; if (value < 0) { @@ -729,10 +768,12 @@ bool step_vm(VM *vm) { return true; } case OP_NEG_INT: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; + u8 dest, src1; + i32 value; src1 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; value = frame->locals[src1]; frame->locals[dest] = -value; @@ -747,53 +788,59 @@ bool step_vm(VM *vm) { case OP_DIV_NAT: MATH_OP(u32, /); case OP_MUL_REAL: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; + u8 dest, src1, src2; src1 = read_u8(vm, code, vm->pc); vm->pc++; src2 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; frame->locals[dest] = fixed_mul(frame->locals[src1], frame->locals[src2]); return true; } case OP_DIV_REAL: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; + u8 dest, src1, src2; src1 = read_u8(vm, code, vm->pc); vm->pc++; src2 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; frame->locals[dest] = fixed_div(frame->locals[src1], frame->locals[src2]); return true; } case OP_ADD_REAL: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; + u8 dest, src1, src2; src1 = read_u8(vm, code, vm->pc); vm->pc++; src2 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; frame->locals[dest] = fixed_add(frame->locals[src1], frame->locals[src2]); return true; } case OP_SUB_REAL: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; + u8 dest, src1, src2; src1 = read_u8(vm, code, vm->pc); vm->pc++; src2 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; frame->locals[dest] = fixed_sub(frame->locals[src1], frame->locals[src2]); return true; } case OP_REAL_TO_INT: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; + u8 dest, src1; + i32 value; src1 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; value = frame->locals[src1]; frame->locals[dest] = fixed_to_int(value); @@ -801,27 +848,31 @@ bool step_vm(VM *vm) { return true; } case OP_INT_TO_REAL: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; + u8 dest, src1; src1 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; frame->locals[dest] = int_to_fixed(frame->locals[src1]); return true; } case OP_REAL_TO_NAT: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; + u8 dest, src1; + u32 value; src1 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; value = frame->locals[src1]; frame->locals[dest] = fixed_to_int(value); return true; } case OP_NAT_TO_REAL: { - dest = read_u8(vm, code, vm->pc); - vm->pc++; + u8 dest, src1; src1 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; frame->locals[dest] = int_to_fixed(frame->locals[src1]); return true; } @@ -880,11 +931,13 @@ bool step_vm(VM *vm) { COMPARE_AND_JUMP(i32, <=); } case OP_INT_TO_STRING: { + u32 ptr; + u8 dest, src1; char buffer[32]; - dest = read_u8(vm, code, vm->pc); - vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; int_to_string(AS_INT(frame->locals[src1]), buffer); ptr = str_alloc(vm, frame, buffer, strlength(buffer)); frame->locals[dest] = ptr; @@ -892,11 +945,13 @@ bool step_vm(VM *vm) { return true; } case OP_NAT_TO_STRING: { + u32 ptr; + u8 dest, src1; char buffer[32]; - dest = read_u8(vm, code, vm->pc); - vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; nat_to_string(frame->locals[src1], buffer); ptr = str_alloc(vm, frame, buffer, strlength(buffer)); frame->locals[dest] = ptr; @@ -904,11 +959,13 @@ bool step_vm(VM *vm) { return true; } case OP_REAL_TO_STRING: { + u32 ptr; + u8 dest, src1; char buffer[32]; - dest = read_u8(vm, code, vm->pc); - vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; fixed_to_string(AS_INT(frame->locals[src1]), buffer); ptr = str_alloc(vm, frame, buffer, strlength(buffer)); /* copy buffer to dest */ @@ -917,11 +974,12 @@ bool step_vm(VM *vm) { return true; } case OP_STRLEN: { + u8 dest, src1; u32 ptr, length; - dest = read_u8(vm, code, vm->pc); - vm->pc++; src1 = read_u8(vm, code, vm->pc); vm->pc++; + dest = read_u8(vm, code, vm->pc); + vm->pc++; ptr = frame->locals[src1]; length = read_u32(vm, memory, ptr); diff --git a/test/add.ul.ir b/test/add.ul.ir index 64e269d..51816fa 100644 --- a/test/add.ul.ir +++ b/test/add.ul.ir @@ -4,14 +4,11 @@ global int x = 1; global int y = 1; function main () - int ans $2; - str ans_string $3; - load_absolute_32 x -> $0; load_absolute_32 y -> $1; - call add $0 $1 -> ans; - int_to_string ans -> ans_string; - call pln ans_string -> void; + call add $0 $1 -> $2; + int_to_string $2 -> $3; + call pln $3; exit 0; function add (int a $0, int b $1) @@ -19,17 +16,20 @@ function add (int a $0, int b $1) add_int a b -> result; return result; -function pln (str message $0) - str term $1; +function pln (str message $0) + plex term $1; int msg_length $2; str nl $3; int nl_length $4; int mode $5; + str term_ns $6; load_immediate 0 -> mode; - syscall OPEN terminal_namespace mode -> term; + load_address terminal_namespace -> term_ns; + syscall OPEN term_ns mode -> term; string_length message -> msg_length; syscall WRITE term message msg_length; - string_length new_line -> nl_length; + load_address new_line -> nl; + string_length nl -> nl_length; syscall WRITE term nl nl_length; return; diff --git a/test/fib.ul.ir b/test/fib.ul.ir index 3ceff47..d283508 100644 --- a/test/fib.ul.ir +++ b/test/fib.ul.ir @@ -30,20 +30,21 @@ function fib (int n $0) else base_case; return n; -function pln (str message $0) - str ts $1; - int mode $5; +function pln (str message $0) + plex term $1; int msg_length $2; str nl $3; int nl_length $4; + int mode $5; + str term_ns $6; - load_immediate terminal_namespace -> ts; load_immediate 0 -> mode; - syscall OPEN ts mode -> ts; + load_address terminal_namespace -> term_ns; + syscall OPEN term_ns mode -> term; string_length message -> msg_length; - syscall WRITE ts message msg_length; - load_immediate new_line -> nl; + syscall WRITE term message msg_length; + load_address new_line -> nl; string_length nl -> nl_length; - syscall WRITE ts nl nl_length; + syscall WRITE term nl nl_length; return; \ No newline at end of file diff --git a/test/hello.ul.ir b/test/hello.ul.ir index c8d2475..4f0a609 100644 --- a/test/hello.ul.ir +++ b/test/hello.ul.ir @@ -1,27 +1,28 @@ -global str terminal_namespace = "/dev/term/0" -global str new_line = "\n" -global str message = "nuqneH 'u'?" +global str terminal_namespace = "/dev/term/0"; +global str new_line = "\n"; +global str message = "nuqneH 'u'?"; function main () str hello $0; - load_immediate message -> hello; - call pln hello -> void; + load_address message -> hello; + call pln hello; exit 0; function pln (str message $0) - str ts $1; - int mode $5; + plex term $1; int msg_length $2; str nl $3; int nl_length $4; + int mode $5; + str term_ns $6; - load_immediate terminal_namespace -> ts; load_immediate 0 -> mode; - syscall OPEN ts mode -> ts; + load_address terminal_namespace -> term_ns; + syscall OPEN term_ns mode -> term; string_length message -> msg_length; - syscall WRITE ts message msg_length; - load_immediate new_line -> nl; + syscall WRITE term message msg_length; + load_address new_line -> nl; string_length nl -> nl_length; - syscall WRITE ts nl nl_length; - return; + syscall WRITE term nl nl_length; + return; \ No newline at end of file diff --git a/test/loop.ul.ir b/test/loop.ul.ir index a9a03b9..06db690 100644 --- a/test/loop.ul.ir +++ b/test/loop.ul.ir @@ -18,41 +18,41 @@ function main () add_int i $3 -> i; jump_ge_int loop_body i $2; - load_immediate terminal_namespace -> term; + load_address terminal_namespace -> term; load_immediate 0 -> mode; syscall OPEN term mode -> term; // Terminal term = open("/dev/term/0", 0); nat b $1; real_to_nat a -> b; - load_immediate prompt -> $7; + load_address prompt -> $7; string_length $7 -> $8; syscall WRITE term $7 $8; // print prompt str user_string $9; load_immediate 32 -> $8; malloc $8 -> user_string; - syscall READ term user_string; $8 // read in max 32 byte string + syscall READ term user_string $8; // read in max 32 byte string - call pln user_string -> void; + call pln user_string; nat_to_string b -> $4; - call pln $4 -> void; + call pln $4; real_to_string a -> $3; - call pln $3 -> void; + call pln $3; exit 0; -function pln (str message $0); - str ts $1; - int mode $5; +function pln (str message $0) + plex term $1; int msg_length $2; str nl $3; int nl_length $4; + int mode $5; - load_immediate terminal_namespace -> ts; + load_address terminal_namespace -> term; load_immediate 0 -> mode; - syscall OPEN ts mode -> ts; + syscall OPEN term mode -> term; // Terminal term = open("/dev/term/0", 0); string_length message -> msg_length; - syscall WRITE ts message msg_length ; - load_immediate new_line -> nl; + syscall WRITE term message msg_length; + load_address new_line -> nl; string_length nl -> nl_length; - syscall WRITE ts nl nl_length; - return; \ No newline at end of file + syscall WRITE term nl nl_length; + return; diff --git a/test/malloc.ul.ir b/test/malloc.ul.ir index 84a883d..87e4109 100644 --- a/test/malloc.ul.ir +++ b/test/malloc.ul.ir @@ -23,18 +23,19 @@ function main () exit 0; function pln (str message $0) - str ts $1; - int mode $5; - int msg_length $2; - str nl $3; + plex term $1; + int msg_length $2; + str nl $3; int nl_length $4; + int mode $5; + str term_ns $6; - load_immediate terminal_namespace -> ts; load_immediate 0 -> mode; - syscall OPEN ts mode -> ts; + load_address terminal_namespace -> term_ns; + syscall OPEN term_ns mode -> term; string_length message -> msg_length; - syscall WRITE ts message msg_length; - load_immediate new_line -> nl; + syscall WRITE term message msg_length; + load_address new_line -> nl; string_length nl -> nl_length; - syscall WRITE ts nl nl_length; - return; + syscall WRITE term nl nl_length; + return; \ No newline at end of file diff --git a/test/simple.ul b/test/simple.ul index 7f7b697..459abcd 100644 --- a/test/simple.ul +++ b/test/simple.ul @@ -2,8 +2,6 @@ * Constants */ const str nl = "\n"; -const real x = 1.0; -const real y = 1.0; plex Terminal { nat handle; @@ -13,7 +11,8 @@ plex Terminal { * Main function */ function main() { - pln((x + y).str); + pln((1.0 + 1.0) as str); + exit(0); } /** diff --git a/test/simple.ul.ir b/test/simple.ul.ir index 803bbde..7c90ce9 100644 --- a/test/simple.ul.ir +++ b/test/simple.ul.ir @@ -1,28 +1,25 @@ global str terminal_namespace = "/dev/term/0"; -global real x = 1.0; -global real y = 1.0; +global str new_line = "\n"; function main () - real a $0; - load_absolute_32 x -> a; - real b $1; - load_absolute_32 y -> b; - real result $2; - add_real a b -> result; - str result_str $3; - real_to_string result -> result_str; - call pln result_str -> void; + load_immediate 1.0 -> $0; + load_immediate 1.0 -> $1; + add_real $0 $1 -> $0; + real_to_string $0 -> $0; + call pln $0; exit 0; function pln (str message $0) - str term $1; + plex term $1; int msg_length $2; str nl $3; int nl_length $4; int mode $5; + str term_ns $6; load_immediate 0 -> mode; - syscall OPEN terminal_namespace mode -> term; + load_address terminal_namespace -> term_ns; + syscall OPEN term_ns mode -> term; string_length message -> msg_length; syscall WRITE term message msg_length; load_address new_line -> nl; diff --git a/test/window.ul.ir b/test/window.ul.ir index d05a596..f8f43fd 100644 --- a/test/window.ul.ir +++ b/test/window.ul.ir @@ -72,18 +72,19 @@ function main () exit 0; function pln (str message $0) - str ts $1; - int mode $5; - int msg_length $2; - str nl $3; + plex term $1; + int msg_length $2; + str nl $3; int nl_length $4; + int mode $5; + str term_ns $6; - load_immediate terminal_namespace -> ts; load_immediate 0 -> mode; - syscall OPEN ts mode -> ts; + load_address terminal_namespace -> term_ns; + syscall OPEN term_ns mode -> term; string_length message -> msg_length; - syscall WRITE ts message msg_length ; - load_immediate new_line -> nl; + syscall WRITE term message msg_length; + load_address new_line -> nl; string_length nl -> nl_length; - syscall WRITE ts nl nl_length; - return; + syscall WRITE term nl nl_length; + return; \ No newline at end of file